cli: merge branch 'th/cli-setting-metadata-bgo732292'

A larger refactoring of nmcli.

Splits out (a bit) the tracking of settings meta data. As such,
it goes towards what is proposed by bgo#732292.

Then, get rid (a bit) of the global data that is passed around.
This commit is contained in:
Thomas Haller 2017-03-30 14:57:54 +02:00
commit 9033d084ab
33 changed files with 9075 additions and 11089 deletions

View file

@ -414,9 +414,10 @@ libnm_core_lib_h_pub_real = \
libnm_core_lib_h_pub_mkenums = \
libnm-core/nm-core-enum-types.h
libnm_core_lib_h_priv = \
shared/nm-utils/nm-enum-utils.h \
shared/nm-utils/nm-shared-utils.h \
shared/nm-utils/nm-udev-utils.h \
shared/nm-setting-metadata.h \
shared/nm-meta-setting.h \
libnm-core/crypto.h \
libnm-core/nm-connection-private.h \
libnm-core/nm-core-internal.h \
@ -427,9 +428,10 @@ libnm_core_lib_h_priv = \
libnm-core/nm-setting-private.h \
libnm-core/nm-utils-private.h
libnm_core_lib_c_real = \
shared/nm-utils/nm-enum-utils.c \
shared/nm-utils/nm-shared-utils.c \
shared/nm-utils/nm-udev-utils.c \
shared/nm-setting-metadata.c \
shared/nm-meta-setting.c \
libnm-core/crypto.c \
libnm-core/nm-connection.c \
libnm-core/nm-dbus-utils.c \
@ -3117,6 +3119,19 @@ if BUILD_NMCLI
bin_PROGRAMS += clients/cli/nmcli
clients_cli_nmcli_SOURCES = \
\
shared/nm-utils/nm-enum-utils.c \
shared/nm-utils/nm-enum-utils.h \
shared/nm-utils/nm-shared-utils.c \
shared/nm-utils/nm-shared-utils.h \
\
shared/nm-meta-setting.c \
shared/nm-meta-setting.h \
\
clients/common/nm-client-utils.c \
clients/common/nm-client-utils.h \
clients/common/nm-meta-setting-desc.c \
clients/common/nm-meta-setting-desc.h \
\
clients/cli/agent.c \
clients/cli/agent.h \

View file

@ -125,7 +125,7 @@ secrets_requested (NMSecretAgentSimple *agent,
NmCli *nmc = (NmCli *) user_data;
gboolean success = FALSE;
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
success = get_secrets_from_user (request_id, title, msg, secrets);

View file

@ -30,56 +30,60 @@
#include <readline/history.h>
#include "nm-vpn-helpers.h"
#include "nm-client-utils.h"
#include "common.h"
#include "utils.h"
extern GMainLoop *loop;
#define OUTPUT_FIELD_WITH_NAME(n) { .name = N_ (n), }
/* Available fields for IPv4 group */
NmcOutputField nmc_fields_ip4_config[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"ADDRESS", N_("ADDRESS")}, /* 1 */
{"GATEWAY", N_("GATEWAY")}, /* 2 */
{"ROUTE", N_("ROUTE")}, /* 3 */
{"DNS", N_("DNS")}, /* 4 */
{"DOMAIN", N_("DOMAIN")}, /* 5 */
{"WINS", N_("WINS")}, /* 6 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("ADDRESS"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("GATEWAY"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("ROUTE"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("DNS"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("DOMAIN"), /* 5 */
OUTPUT_FIELD_WITH_NAME ("WINS"), /* 6 */
{ 0 }
};
#define NMC_FIELDS_IP4_CONFIG_ALL "GROUP,ADDRESS,GATEWAY,ROUTE,DNS,DOMAIN,WINS"
/* Available fields for DHCPv4 group */
NmcOutputField nmc_fields_dhcp4_config[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"OPTION", N_("OPTION")}, /* 1 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("OPTION"), /* 1 */
{ 0 }
};
#define NMC_FIELDS_DHCP4_CONFIG_ALL "GROUP,OPTION"
/* Available fields for IPv6 group */
NmcOutputField nmc_fields_ip6_config[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"ADDRESS", N_("ADDRESS")}, /* 1 */
{"GATEWAY", N_("GATEWAY")}, /* 2 */
{"ROUTE", N_("ROUTE")}, /* 3 */
{"DNS", N_("DNS")}, /* 4 */
{"DOMAIN", N_("DOMAIN")}, /* 5 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("ADDRESS"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("GATEWAY"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("ROUTE"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("DNS"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("DOMAIN"), /* 5 */
{ 0 }
};
#define NMC_FIELDS_IP6_CONFIG_ALL "GROUP,ADDRESS,GATEWAY,ROUTE,DNS,DOMAIN"
/* Available fields for DHCPv6 group */
NmcOutputField nmc_fields_dhcp6_config[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"OPTION", N_("OPTION")}, /* 1 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("OPTION"), /* 1 */
{ 0 }
};
#define NMC_FIELDS_DHCP6_CONFIG_ALL "GROUP,OPTION"
gboolean
print_ip4_config (NMIPConfig *cfg4,
NmCli *nmc,
const NmcConfig *nmc_config,
const char *group_prefix,
const char *one_field)
{
@ -92,16 +96,17 @@ print_ip4_config (NMIPConfig *cfg4,
int i = 0;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (cfg4 == NULL)
return FALSE;
tmpl = nmc_fields_ip4_config;
tmpl_len = sizeof (nmc_fields_ip4_config);
nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP4_CONFIG_ALL,
out.print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP4_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
/* addresses */
ptr_array = nm_ip_config_get_addresses (cfg4);
@ -156,19 +161,17 @@ print_ip4_config (NMIPConfig *cfg4,
set_val_arr (arr, 4, dns_arr);
set_val_arr (arr, 5, domain_arr);
set_val_arr (arr, 6, wins_arr);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
/* Remove any previous data */
nmc_empty_output_fields (nmc);
print_data_prepare_width (out.output_data);
print_data (nmc_config, &out);
return TRUE;
}
gboolean
print_ip6_config (NMIPConfig *cfg6,
NmCli *nmc,
const NmcConfig *nmc_config,
const char *group_prefix,
const char *one_field)
{
@ -180,16 +183,17 @@ print_ip6_config (NMIPConfig *cfg6,
int i = 0;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (cfg6 == NULL)
return FALSE;
tmpl = nmc_fields_ip6_config;
tmpl_len = sizeof (nmc_fields_ip6_config);
nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP6_CONFIG_ALL,
out.print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_IP6_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
/* addresses */
ptr_array = nm_ip_config_get_addresses (cfg6);
@ -240,19 +244,17 @@ print_ip6_config (NMIPConfig *cfg6,
set_val_arr (arr, 3, route_arr);
set_val_arr (arr, 4, dns_arr);
set_val_arr (arr, 5, domain_arr);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
/* Remove any previous data */
nmc_empty_output_fields (nmc);
print_data_prepare_width (out.output_data);
print_data (nmc_config, &out);
return TRUE;
}
gboolean
print_dhcp4_config (NMDhcpConfig *dhcp4,
NmCli *nmc,
const NmcConfig *nmc_config,
const char *group_prefix,
const char *one_field)
{
@ -269,13 +271,14 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
gpointer key, value;
char **options_arr = NULL;
int i = 0;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
tmpl = nmc_fields_dhcp4_config;
tmpl_len = sizeof (nmc_fields_dhcp4_config);
nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP4_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
out.print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP4_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
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);
@ -286,12 +289,10 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
set_val_strc (arr, 0, group_prefix);
set_val_arr (arr, 1, options_arr);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
/* Remove any previous data */
nmc_empty_output_fields (nmc);
print_data_prepare_width (out.output_data);
print_data (nmc_config, &out);
return TRUE;
}
@ -300,7 +301,7 @@ print_dhcp4_config (NMDhcpConfig *dhcp4,
gboolean
print_dhcp6_config (NMDhcpConfig *dhcp6,
NmCli *nmc,
const NmcConfig *nmc_config,
const char *group_prefix,
const char *one_field)
{
@ -317,13 +318,14 @@ print_dhcp6_config (NMDhcpConfig *dhcp6,
gpointer key, value;
char **options_arr = NULL;
int i = 0;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
tmpl = nmc_fields_dhcp6_config;
tmpl_len = sizeof (nmc_fields_dhcp6_config);
nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP6_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
out.print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DHCP6_CONFIG_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
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);
@ -334,205 +336,16 @@ print_dhcp6_config (NMDhcpConfig *dhcp6,
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
set_val_strc (arr, 0, group_prefix);
set_val_arr (arr, 1, options_arr);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
/* Remove any previous data */
nmc_empty_output_fields (nmc);
print_data_prepare_width (out.output_data);
print_data (nmc_config, &out);
return TRUE;
}
return FALSE;
}
/*
* Parse IP address from string to NMIPAddress stucture.
* ip_str is the IP address in the form address/prefix
*/
NMIPAddress *
nmc_parse_and_build_address (int family, const char *ip_str, GError **error)
{
int max_prefix = (family == AF_INET) ? 32 : 128;
NMIPAddress *addr = NULL;
const char *ip;
char *tmp;
char *plen;
long int prefix;
GError *local = NULL;
g_return_val_if_fail (ip_str != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
tmp = g_strdup (ip_str);
plen = strchr (tmp, '/'); /* prefix delimiter */
if (plen)
*plen++ = '\0';
ip = tmp;
prefix = max_prefix;
if (plen) {
if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid prefix '%s'; <1-%d> allowed"), plen, max_prefix);
goto finish;
}
}
addr = nm_ip_address_new (family, ip, (guint32) prefix, &local);
if (!addr) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid IP address: %s"), local->message);
g_clear_error (&local);
}
finish:
g_free (tmp);
return addr;
}
/*
* nmc_parse_and_build_route:
* @family: AF_INET or AF_INET6
* @str: route string to be parsed
* @error: location to store GError
*
* Parse route from string and return an #NMIPRoute
*
* Returns: a new #NMIPRoute or %NULL on error
*/
NMIPRoute *
nmc_parse_and_build_route (int family,
const char *str,
GError **error)
{
int max_prefix = (family == AF_INET) ? 32 : 128;
char *plen = NULL;
const char *next_hop = NULL;
const char *canon_dest;
long int prefix = max_prefix;
unsigned long int tmp_ulong;
NMIPRoute *route = NULL;
gboolean success = FALSE;
GError *local = NULL;
gint64 metric = -1;
guint i, len;
gs_strfreev char **routev = NULL;
gs_free char *value = NULL;
gs_free char *dest = NULL;
gs_unref_hashtable GHashTable *attrs = NULL;
GHashTable *tmp_attrs;
g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE);
g_return_val_if_fail (str, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
value = g_strdup (str);
routev = nmc_strsplit_set (g_strstrip (value), " \t", 0);
len = g_strv_length (routev);
if (len < 1) {
g_set_error (error, 1, 0, _("'%s' is not valid (the format is: ip[/prefix] [next-hop] [metric] [attr=val] [attr=val])"),
str);
goto finish;
}
dest = g_strdup (routev[0]);
plen = strchr (dest, '/'); /* prefix delimiter */
if (plen)
*plen++ = '\0';
if (plen) {
if (!nmc_string_to_int (plen, TRUE, 1, max_prefix, &prefix)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid prefix '%s'; <1-%d> allowed"),
plen, max_prefix);
goto finish;
}
}
for (i = 1; i < len; i++) {
if (nm_utils_ipaddr_valid (family, routev[i])) {
if (metric != -1 || attrs) {
g_set_error (error, 1, 0, _("the next hop ('%s') must be first"), routev[i]);
goto finish;
}
next_hop = routev[i];
} else if (nmc_string_to_uint (routev[i], TRUE, 0, G_MAXUINT32, &tmp_ulong)) {
if (attrs) {
g_set_error (error, 1, 0, _("the metric ('%s') must be before attributes"), routev[i]);
goto finish;
}
metric = tmp_ulong;
} else if (strchr (routev[i], '=')) {
GHashTableIter iter;
char *iter_key;
GVariant *iter_value;
tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE,
nm_ip_route_get_variant_attribute_spec(),
error);
if (!tmp_attrs) {
g_prefix_error (error, "invalid option '%s': ", routev[i]);
goto finish;
}
if (!attrs)
attrs = g_hash_table_new (g_str_hash, g_str_equal);
g_hash_table_iter_init (&iter, tmp_attrs);
while (g_hash_table_iter_next (&iter, (gpointer *) &iter_key, (gpointer *) &iter_value)) {
if (!nm_ip_route_attribute_validate (iter_key, iter_value, family, NULL, error)) {
g_prefix_error (error, "%s: ", iter_key);
g_hash_table_unref (tmp_attrs);
goto finish;
}
g_hash_table_insert (attrs, iter_key, iter_value);
g_hash_table_iter_steal (&iter);
}
g_hash_table_unref (tmp_attrs);
} else {
g_set_error (error, 1, 0, _("unrecognized option '%s'"), routev[i]);
goto finish;
}
}
route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local);
if (!route) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("invalid route: %s"), local->message);
g_clear_error (&local);
goto finish;
}
/* We don't accept default routes as NetworkManager handles it
* itself. But we have to check this after @route has normalized the
* dest string.
*/
canon_dest = nm_ip_route_get_dest (route);
if (!strcmp (canon_dest, "0.0.0.0") || !strcmp (canon_dest, "::")) {
g_set_error_literal (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("default route cannot be added (NetworkManager handles it by itself)"));
g_clear_pointer (&route, nm_ip_route_unref);
goto finish;
}
if (attrs) {
GHashTableIter iter;
char *name;
GVariant *variant;
g_hash_table_iter_init (&iter, attrs);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant))
nm_ip_route_set_attribute (route, name, variant);
}
success = TRUE;
finish:
return route;
}
const char *
nmc_device_state_to_string (NMDeviceState state)
{
@ -782,240 +595,6 @@ nmc_device_reason_to_string (NMDeviceStateReason reason)
}
}
/* Max priority values from libnm-core/nm-setting-vlan.c */
#define MAX_SKB_PRIO G_MAXUINT32
#define MAX_8021P_PRIO 7 /* Max 802.1p priority */
/*
* Parse VLAN priority mappings from the following format: 2:1,3:4,7:3
* and verify if the priority numbers are valid
*
* Return: string array with split maps, or NULL on error
* Caller is responsible for freeing the array.
*/
char **
nmc_vlan_parse_priority_maps (const char *priority_map,
NMVlanPriorityMap map_type,
GError **error)
{
char **mapping = NULL, **iter;
unsigned long from, to, from_max, to_max;
g_return_val_if_fail (priority_map != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (map_type == NM_VLAN_INGRESS_MAP) {
from_max = MAX_8021P_PRIO;
to_max = MAX_SKB_PRIO;
} else {
from_max = MAX_SKB_PRIO;
to_max = MAX_8021P_PRIO;
}
mapping = g_strsplit (priority_map, ",", 0);
for (iter = mapping; iter && *iter; iter++) {
char *left, *right;
left = g_strstrip (*iter);
right = strchr (left, ':');
if (!right) {
g_set_error (error, 1, 0, _("invalid priority map '%s'"), *iter);
g_strfreev (mapping);
return NULL;
}
*right++ = '\0';
if (!nmc_string_to_uint (left, TRUE, 0, from_max, &from)) {
g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"),
left, from_max);
g_strfreev (mapping);
return NULL;
}
if (!nmc_string_to_uint (right, TRUE, 0, to_max, &to)) {
g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"),
right, to_max);
g_strfreev (mapping);
return NULL;
}
*(right-1) = ':'; /* Put back ':' */
}
return mapping;
}
const char *
nmc_bond_validate_mode (const char *mode, GError **error)
{
unsigned long mode_int;
static const char *valid_modes[] = { "balance-rr",
"active-backup",
"balance-xor",
"broadcast",
"802.3ad",
"balance-tlb",
"balance-alb",
NULL };
if (nmc_string_to_uint (mode, TRUE, 0, 6, &mode_int)) {
/* Translate bonding mode numbers to mode names:
* https://www.kernel.org/doc/Documentation/networking/bonding.txt
*/
return valid_modes[mode_int];
} else
return nmc_string_is_valid (mode, valid_modes, error);
}
/*
* nmc_team_check_config:
* @config: file name with team config, or raw team JSON config data
* @out_config: raw team JSON config data
* The value must be freed with g_free().
* @error: location to store error, or %NUL
*
* Check team config from @config parameter and return the checked
* config in @out_config.
*
* Returns: %TRUE if the config is valid, %FALSE if it is invalid
*/
gboolean
nmc_team_check_config (const char *config, char **out_config, GError **error)
{
enum {
_TEAM_CONFIG_TYPE_GUESS,
_TEAM_CONFIG_TYPE_FILE,
_TEAM_CONFIG_TYPE_JSON,
} desired_type = _TEAM_CONFIG_TYPE_GUESS;
const char *filename = NULL;
size_t c_len = 0;
gs_free char *config_clone = NULL;
*out_config = NULL;
if (!config || !config[0])
return TRUE;
if (g_str_has_prefix (config, "file://")) {
config += NM_STRLEN ("file://");
desired_type = _TEAM_CONFIG_TYPE_FILE;
} else if (g_str_has_prefix (config, "json://")) {
config += NM_STRLEN ("json://");
desired_type = _TEAM_CONFIG_TYPE_JSON;
}
if (NM_IN_SET (desired_type, _TEAM_CONFIG_TYPE_FILE, _TEAM_CONFIG_TYPE_GUESS)) {
gs_free char *contents = NULL;
if (!g_file_get_contents (config, &contents, &c_len, NULL)) {
if (desired_type == _TEAM_CONFIG_TYPE_FILE) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("cannot read team config from file '%s'"),
config);
return FALSE;
}
} else {
if (c_len != strlen (contents)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("team config file '%s' contains non-valid utf-8"),
config);
return FALSE;
}
filename = config;
config = config_clone = g_steal_pointer (&contents);
}
}
if (!nm_utils_is_json_object (config, NULL)) {
if (filename) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("'%s' does not contain a valid team configuration"), filename);
} else {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("team configuration must be a JSON object"));
}
return FALSE;
}
*out_config = (config == config_clone)
? g_steal_pointer (&config_clone)
: g_strdup (config);
return TRUE;
}
/*
* nmc_proxy_check_script:
* @script: file name with PAC script, or raw PAC Script data
* @out_script: raw PAC Script (with removed new-line characters)
* @error: location to store error, or %NULL
*
* Check PAC Script from @script parameter and return the checked/sanitized
* config in @out_script.
*
* Returns: %TRUE if the script is valid, %FALSE if it is invalid
*/
gboolean
nmc_proxy_check_script (const char *script, char **out_script, GError **error)
{
enum {
_PAC_SCRIPT_TYPE_GUESS,
_PAC_SCRIPT_TYPE_FILE,
_PAC_SCRIPT_TYPE_JSON,
} desired_type = _PAC_SCRIPT_TYPE_GUESS;
const char *filename = NULL;
size_t c_len = 0;
gs_free char *script_clone = NULL;
*out_script = NULL;
if (!script || !script[0])
return TRUE;
if (g_str_has_prefix (script, "file://")) {
script += NM_STRLEN ("file://");
desired_type = _PAC_SCRIPT_TYPE_FILE;
} else if (g_str_has_prefix (script, "js://")) {
script += NM_STRLEN ("js://");
desired_type = _PAC_SCRIPT_TYPE_JSON;
}
if (NM_IN_SET (desired_type, _PAC_SCRIPT_TYPE_FILE, _PAC_SCRIPT_TYPE_GUESS)) {
gs_free char *contents = NULL;
if (!g_file_get_contents (script, &contents, &c_len, NULL)) {
if (desired_type == _PAC_SCRIPT_TYPE_FILE) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("cannot read pac-script from file '%s'"),
script);
return FALSE;
}
} else {
if (c_len != strlen (contents)) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("file '%s' contains non-valid utf-8"),
script);
return FALSE;
}
filename = script;
script = script_clone = g_steal_pointer (&contents);
}
}
if ( !strstr (script, "FindProxyForURL")
|| !g_utf8_validate (script, -1, NULL)) {
if (filename) {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("'%s' does not contain a valid PAC Script"), filename);
} else {
g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
_("Not a valid PAC Script"));
}
return FALSE;
}
*out_script = (script == script_clone)
? g_steal_pointer (&script_clone)
: g_strdup (script);
return TRUE;
}
/*
* nmc_find_connection:
* @connections: array of NMConnections to search in
@ -1260,7 +839,7 @@ nmc_secrets_requested (NMSecretAgentSimple *agent,
gboolean success = FALSE;
const GPtrArray *connections;
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
/* Find the connection for the request */
@ -1274,7 +853,7 @@ nmc_secrets_requested (NMSecretAgentSimple *agent,
g_free (path);
}
success = get_secrets_from_user (request_id, title, msg, connection, nmc->in_editor || nmc->ask,
success = get_secrets_from_user (request_id, title, msg, connection, nmc->nmc_config.in_editor || nmc->ask,
nmc->show_secrets, nmc->pwds_hash, secrets);
if (success)
nm_secret_agent_simple_response (agent, request_id, secrets);
@ -1393,7 +972,7 @@ read_again:
if (nmc_seen_sigint ()) {
/* Ctrl-C */
nmc_clear_sigint ();
if ( nm_cli.in_editor
if ( nm_cli.nmc_config.in_editor
|| (rl_string && *rl_string)) {
/* In editor, or the line is not empty */
/* Call readline again to get new prompt (repeat) */
@ -1500,7 +1079,7 @@ nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...)
* See e.g. http://cnswww.cns.cwru.edu/php/chet/readline/readline.html#SEC49
*/
char *
nmc_rl_gen_func_basic (const char *text, int state, const char **words)
nmc_rl_gen_func_basic (const char *text, int state, const char *const*words)
{
static int list_idx, len;
const char *name;

View file

@ -25,27 +25,15 @@
#include "nmcli.h"
#include "nm-secret-agent-simple.h"
gboolean print_ip4_config (NMIPConfig *cfg4, NmCli *nmc, const char *group_prefix, const char *one_field);
gboolean print_ip6_config (NMIPConfig *cfg6, NmCli *nmc, const char *group_prefix, const char *one_field);
gboolean print_dhcp4_config (NMDhcpConfig *dhcp4, NmCli *nmc, const char *group_prefix, const char *one_field);
gboolean print_dhcp6_config (NMDhcpConfig *dhcp6, NmCli *nmc, const char *group_prefix, const char *one_field);
NMIPAddress *nmc_parse_and_build_address (int family, const char *ip_str, GError **error);
NMIPRoute *nmc_parse_and_build_route (int family, const char *str, GError **error);
gboolean print_ip4_config (NMIPConfig *cfg4, const NmcConfig *nmc_config, const char *group_prefix, 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);
const char * nmc_device_state_to_string (NMDeviceState state);
const char * nmc_device_reason_to_string (NMDeviceStateReason reason);
const char * nmc_device_metered_to_string (NMMetered value);
char **
nmc_vlan_parse_priority_maps (const char *priority_map,
NMVlanPriorityMap map_type,
GError **error);
const char *nmc_bond_validate_mode (const char *mode, GError **error);
gboolean nmc_team_check_config (const char *config, char **out_config, GError **error);
gboolean nmc_proxy_check_script (const char *script, char **out_script, GError **error);
NMConnection *nmc_find_connection (const GPtrArray *connections,
const char *filter_type,
const char *filter_val,
@ -65,7 +53,7 @@ char *nmc_unique_connection_name (const GPtrArray *connections,
void nmc_cleanup_readline (void);
char *nmc_readline (const char *prompt_fmt, ...) G_GNUC_PRINTF (1, 2);
char *nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...) G_GNUC_PRINTF (2, 3);
char *nmc_rl_gen_func_basic (const char *text, int state, const char **words);
char *nmc_rl_gen_func_basic (const char *text, int state, const char *const*words);
char *nmc_rl_gen_func_ifnames (const char *text, int state);
gboolean nmc_get_in_readline (void);
void nmc_set_in_readline (gboolean in_readline);

View file

@ -29,6 +29,8 @@
#include <readline/readline.h>
#include <readline/history.h>
#include "nm-client-utils.h"
#include "utils.h"
#include "common.h"
#include "settings.h"
@ -38,6 +40,9 @@
#include "polkit-agent.h"
#include "nm-vpn-helpers.h"
#define OUTPUT_FIELD_WITH_NAME(n) { .name = N_ (n), }
#define OUTPUT_FIELD_WITH_FIELDS(n, fields) { .name = N_ (n), .group_list = fields + 1, }
typedef struct _OptionInfo OptionInfo;
struct _OptionInfo {
const char *setting_name;
@ -127,66 +132,70 @@ struct _OptionInfo {
/* Available fields for 'connection show' */
NmcOutputField nmc_fields_con_show[] = {
{"NAME", N_("NAME")}, /* 0 */
{"UUID", N_("UUID")}, /* 1 */
{"TYPE", N_("TYPE")}, /* 2 */
{"TIMESTAMP", N_("TIMESTAMP")}, /* 3 */
{"TIMESTAMP-REAL", N_("TIMESTAMP-REAL")}, /* 4 */
{"AUTOCONNECT", N_("AUTOCONNECT")}, /* 5 */
{"AUTOCONNECT-PRIORITY", N_("AUTOCONNECT-PRIORITY")}, /* 6 */
{"READONLY", N_("READONLY")}, /* 7 */
{"DBUS-PATH", N_("DBUS-PATH")}, /* 8 */
{"ACTIVE", N_("ACTIVE")}, /* 9 */
{"DEVICE", N_("DEVICE")}, /* 10 */
{"STATE", N_("STATE")}, /* 11 */
{"ACTIVE-PATH", N_("ACTIVE-PATH")}, /* 12 */
{"SLAVE", N_("SLAVE")}, /* 13 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("NAME"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("UUID"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("TYPE"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("TIMESTAMP"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("TIMESTAMP-REAL"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("AUTOCONNECT"), /* 5 */
OUTPUT_FIELD_WITH_NAME ("AUTOCONNECT-PRIORITY"), /* 6 */
OUTPUT_FIELD_WITH_NAME ("READONLY"), /* 7 */
OUTPUT_FIELD_WITH_NAME ("DBUS-PATH"), /* 8 */
OUTPUT_FIELD_WITH_NAME ("ACTIVE"), /* 9 */
OUTPUT_FIELD_WITH_NAME ("DEVICE"), /* 10 */
OUTPUT_FIELD_WITH_NAME ("STATE"), /* 11 */
OUTPUT_FIELD_WITH_NAME ("ACTIVE-PATH"), /* 12 */
OUTPUT_FIELD_WITH_NAME ("SLAVE"), /* 13 */
{ 0 }
};
#define NMC_FIELDS_CON_SHOW_ALL "NAME,UUID,TYPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,AUTOCONNECT-PRIORITY,READONLY,DBUS-PATH,"\
"ACTIVE,DEVICE,STATE,ACTIVE-PATH,SLAVE"
#define NMC_FIELDS_CON_SHOW_COMMON "NAME,UUID,TYPE,DEVICE"
/* Helper macro to define fields */
#define SETTING_FIELD(setting, props) { setting, N_(setting), 0, props, NULL, FALSE, FALSE, 0 }
#define OUTPUT_FIELD_WITH_SETTING(setting, setting_type) \
{ \
.name = setting, \
.setting_info = &nm_meta_setting_infos_editor[setting_type], \
}
/* Available settings for 'connection show <con>' - profile part */
NmcOutputField nmc_fields_settings_names[] = {
SETTING_FIELD (NM_SETTING_CONNECTION_SETTING_NAME, nmc_fields_setting_connection + 1), /* 0 */
SETTING_FIELD (NM_SETTING_WIRED_SETTING_NAME, nmc_fields_setting_wired + 1), /* 1 */
SETTING_FIELD (NM_SETTING_802_1X_SETTING_NAME, nmc_fields_setting_8021X + 1), /* 2 */
SETTING_FIELD (NM_SETTING_WIRELESS_SETTING_NAME, nmc_fields_setting_wireless + 1), /* 3 */
SETTING_FIELD (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, nmc_fields_setting_wireless_security + 1), /* 4 */
SETTING_FIELD (NM_SETTING_IP4_CONFIG_SETTING_NAME, nmc_fields_setting_ip4_config + 1), /* 5 */
SETTING_FIELD (NM_SETTING_IP6_CONFIG_SETTING_NAME, nmc_fields_setting_ip6_config + 1), /* 6 */
SETTING_FIELD (NM_SETTING_SERIAL_SETTING_NAME, nmc_fields_setting_serial + 1), /* 7 */
SETTING_FIELD (NM_SETTING_PPP_SETTING_NAME, nmc_fields_setting_ppp + 1), /* 8 */
SETTING_FIELD (NM_SETTING_PPPOE_SETTING_NAME, nmc_fields_setting_pppoe + 1), /* 9 */
SETTING_FIELD (NM_SETTING_GSM_SETTING_NAME, nmc_fields_setting_gsm + 1), /* 10 */
SETTING_FIELD (NM_SETTING_CDMA_SETTING_NAME, nmc_fields_setting_cdma + 1), /* 11 */
SETTING_FIELD (NM_SETTING_BLUETOOTH_SETTING_NAME, nmc_fields_setting_bluetooth + 1), /* 12 */
SETTING_FIELD (NM_SETTING_OLPC_MESH_SETTING_NAME, nmc_fields_setting_olpc_mesh + 1), /* 13 */
SETTING_FIELD (NM_SETTING_VPN_SETTING_NAME, nmc_fields_setting_vpn + 1), /* 14 */
SETTING_FIELD (NM_SETTING_WIMAX_SETTING_NAME, nmc_fields_setting_wimax + 1), /* 15 */
SETTING_FIELD (NM_SETTING_INFINIBAND_SETTING_NAME, nmc_fields_setting_infiniband + 1), /* 16 */
SETTING_FIELD (NM_SETTING_BOND_SETTING_NAME, nmc_fields_setting_bond + 1), /* 17 */
SETTING_FIELD (NM_SETTING_VLAN_SETTING_NAME, nmc_fields_setting_vlan + 1), /* 18 */
SETTING_FIELD (NM_SETTING_ADSL_SETTING_NAME, nmc_fields_setting_adsl + 1), /* 19 */
SETTING_FIELD (NM_SETTING_BRIDGE_SETTING_NAME, nmc_fields_setting_bridge + 1), /* 20 */
SETTING_FIELD (NM_SETTING_BRIDGE_PORT_SETTING_NAME, nmc_fields_setting_bridge_port + 1), /* 21 */
SETTING_FIELD (NM_SETTING_TEAM_SETTING_NAME, nmc_fields_setting_team + 1), /* 22 */
SETTING_FIELD (NM_SETTING_TEAM_PORT_SETTING_NAME, nmc_fields_setting_team_port + 1), /* 23 */
SETTING_FIELD (NM_SETTING_DCB_SETTING_NAME, nmc_fields_setting_dcb + 1), /* 24 */
SETTING_FIELD (NM_SETTING_TUN_SETTING_NAME, nmc_fields_setting_tun + 1), /* 25 */
SETTING_FIELD (NM_SETTING_IP_TUNNEL_SETTING_NAME, nmc_fields_setting_ip_tunnel + 1), /* 26 */
SETTING_FIELD (NM_SETTING_MACSEC_SETTING_NAME, nmc_fields_setting_macsec + 1), /* 27 */
SETTING_FIELD (NM_SETTING_MACVLAN_SETTING_NAME, nmc_fields_setting_macvlan + 1), /* 28 */
SETTING_FIELD (NM_SETTING_VXLAN_SETTING_NAME, nmc_fields_setting_vxlan + 1), /* 29 */
SETTING_FIELD (NM_SETTING_PROXY_SETTING_NAME, nmc_fields_setting_proxy + 1), /* 30 */
SETTING_FIELD (NM_SETTING_DUMMY_SETTING_NAME, nmc_fields_setting_dummy + 1), /* 31 */
{NULL, NULL, 0, NULL, NULL, FALSE, FALSE, 0}
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_CONNECTION_SETTING_NAME, NM_META_SETTING_TYPE_CONNECTION), /* 0 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_WIRED_SETTING_NAME, NM_META_SETTING_TYPE_WIRED), /* 1 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_802_1X_SETTING_NAME, NM_META_SETTING_TYPE_802_1X), /* 2 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_WIRELESS_SETTING_NAME, NM_META_SETTING_TYPE_WIRELESS), /* 3 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_META_SETTING_TYPE_WIRELESS_SECURITY), /* 4 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_META_SETTING_TYPE_IP4_CONFIG), /* 5 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_META_SETTING_TYPE_IP6_CONFIG), /* 6 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_SERIAL_SETTING_NAME, NM_META_SETTING_TYPE_SERIAL), /* 7 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_PPP_SETTING_NAME, NM_META_SETTING_TYPE_PPP), /* 8 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_PPPOE_SETTING_NAME, NM_META_SETTING_TYPE_PPPOE), /* 9 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_GSM_SETTING_NAME, NM_META_SETTING_TYPE_GSM), /* 10 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_CDMA_SETTING_NAME, NM_META_SETTING_TYPE_CDMA), /* 11 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME, NM_META_SETTING_TYPE_BLUETOOTH), /* 12 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_OLPC_MESH_SETTING_NAME, NM_META_SETTING_TYPE_OLPC_MESH), /* 13 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_VPN_SETTING_NAME, NM_META_SETTING_TYPE_VPN), /* 14 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_WIMAX_SETTING_NAME, NM_META_SETTING_TYPE_WIMAX), /* 15 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME, NM_META_SETTING_TYPE_INFINIBAND), /* 16 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_BOND_SETTING_NAME, NM_META_SETTING_TYPE_BOND), /* 17 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_VLAN_SETTING_NAME, NM_META_SETTING_TYPE_VLAN), /* 18 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_ADSL_SETTING_NAME, NM_META_SETTING_TYPE_ADSL), /* 19 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_BRIDGE_SETTING_NAME, NM_META_SETTING_TYPE_BRIDGE), /* 20 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_BRIDGE_PORT_SETTING_NAME, NM_META_SETTING_TYPE_BRIDGE_PORT), /* 21 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_TEAM_SETTING_NAME, NM_META_SETTING_TYPE_TEAM), /* 22 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME, NM_META_SETTING_TYPE_TEAM_PORT), /* 23 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_DCB_SETTING_NAME, NM_META_SETTING_TYPE_DCB), /* 24 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_TUN_SETTING_NAME, NM_META_SETTING_TYPE_TUN), /* 25 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_IP_TUNNEL_SETTING_NAME, NM_META_SETTING_TYPE_IP_TUNNEL), /* 26 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_MACSEC_SETTING_NAME, NM_META_SETTING_TYPE_MACSEC), /* 27 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_MACVLAN_SETTING_NAME, NM_META_SETTING_TYPE_MACVLAN), /* 28 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_VXLAN_SETTING_NAME, NM_META_SETTING_TYPE_VXLAN), /* 29 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_PROXY_SETTING_NAME, NM_META_SETTING_TYPE_PROXY), /* 30 */
OUTPUT_FIELD_WITH_SETTING (NM_SETTING_DUMMY_SETTING_NAME, NM_META_SETTING_TYPE_DUMMY), /* 31 */
{ 0 }
};
#define NMC_FIELDS_SETTINGS_NAMES_ALL_X NM_SETTING_CONNECTION_SETTING_NAME","\
#define NMC_FIELDS_SETTINGS_NAMES_ALL NM_SETTING_CONNECTION_SETTING_NAME","\
NM_SETTING_WIRED_SETTING_NAME","\
NM_SETTING_802_1X_SETTING_NAME","\
NM_SETTING_WIRELESS_SETTING_NAME","\
@ -216,25 +225,26 @@ NmcOutputField nmc_fields_settings_names[] = {
NM_SETTING_MACVLAN_SETTING_NAME"," \
NM_SETTING_VXLAN_SETTING_NAME"," \
NM_SETTING_PROXY_SETTING_NAME
#define NMC_FIELDS_SETTINGS_NAMES_ALL NMC_FIELDS_SETTINGS_NAMES_ALL_X
// NM_SETTING_DUMMY_SETTING_NAME
// NM_SETTING_WIMAX_SETTING_NAME
/* Active connection data */
/* Available fields for GENERAL group */
NmcOutputField nmc_fields_con_active_details_general[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"NAME", N_("NAME")}, /* 1 */
{"UUID", N_("UUID")}, /* 2 */
{"DEVICES", N_("DEVICES")}, /* 3 */
{"STATE", N_("STATE")}, /* 4 */
{"DEFAULT", N_("DEFAULT")}, /* 5 */
{"DEFAULT6", N_("DEFAULT6")}, /* 6 */
{"SPEC-OBJECT", N_("SPEC-OBJECT")}, /* 7 */
{"VPN", N_("VPN")}, /* 8 */
{"DBUS-PATH", N_("DBUS-PATH")}, /* 9 */
{"CON-PATH", N_("CON-PATH")}, /* 10 */
{"ZONE", N_("ZONE")}, /* 11 */
{"MASTER-PATH", N_("MASTER-PATH")}, /* 12 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("NAME"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("UUID"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("DEVICES"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("STATE"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("DEFAULT"), /* 5 */
OUTPUT_FIELD_WITH_NAME ("DEFAULT6"), /* 6 */
OUTPUT_FIELD_WITH_NAME ("SPEC-OBJECT"), /* 7 */
OUTPUT_FIELD_WITH_NAME ("VPN"), /* 8 */
OUTPUT_FIELD_WITH_NAME ("DBUS-PATH"), /* 9 */
OUTPUT_FIELD_WITH_NAME ("CON-PATH"), /* 10 */
OUTPUT_FIELD_WITH_NAME ("ZONE"), /* 11 */
OUTPUT_FIELD_WITH_NAME ("MASTER-PATH"), /* 12 */
{ 0 }
};
#define NMC_FIELDS_CON_ACTIVE_DETAILS_GENERAL_ALL "GROUP,NAME,UUID,DEVICES,STATE,DEFAULT,DEFAULT6,"\
"VPN,ZONE,DBUS-PATH,CON-PATH,SPEC-OBJECT,MASTER-PATH"
@ -243,14 +253,14 @@ NmcOutputField nmc_fields_con_active_details_general[] = {
/* Available fields for VPN group */
NmcOutputField nmc_fields_con_active_details_vpn[] = {
{"GROUP", N_("GROUP")}, /* 0 */
{"TYPE", N_("TYPE")}, /* 1 */
{"USERNAME", N_("USERNAME")}, /* 2 */
{"GATEWAY", N_("GATEWAY")}, /* 3 */
{"BANNER", N_("BANNER")}, /* 4 */
{"VPN-STATE", N_("VPN-STATE")}, /* 5 */
{"CFG", N_("CFG")}, /* 6 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("GROUP"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("TYPE"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("USERNAME"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("GATEWAY"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("BANNER"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("VPN-STATE"), /* 5 */
OUTPUT_FIELD_WITH_NAME ("CFG"), /* 6 */
{ 0 }
};
#define NMC_FIELDS_CON_ACTIVE_DETAILS_VPN_ALL "GROUP,TYPE,USERNAME,GATEWAY,BANNER,VPN-STATE,CFG"
@ -262,13 +272,13 @@ extern NmcOutputField nmc_fields_dhcp6_config[];
/* Available fields for 'connection show <con>' - active part */
NmcOutputField nmc_fields_con_active_details_groups[] = {
{"GENERAL", N_("GENERAL"), 0, nmc_fields_con_active_details_general + 1}, /* 0 */
{"IP4", N_("IP4"), 0, nmc_fields_ip4_config + 1 }, /* 1 */
{"DHCP4", N_("DHCP4"), 0, nmc_fields_dhcp4_config + 1 }, /* 2 */
{"IP6", N_("IP6"), 0, nmc_fields_ip6_config + 1 }, /* 3 */
{"DHCP6", N_("DHCP6"), 0, nmc_fields_dhcp6_config + 1 }, /* 4 */
{"VPN", N_("VPN"), 0, nmc_fields_con_active_details_vpn + 1 }, /* 5 */
{NULL, NULL, 0, NULL}
OUTPUT_FIELD_WITH_FIELDS ("GENERAL", nmc_fields_con_active_details_general), /* 0 */
OUTPUT_FIELD_WITH_FIELDS ("IP4", nmc_fields_ip4_config), /* 1 */
OUTPUT_FIELD_WITH_FIELDS ("DHCP4", nmc_fields_dhcp4_config), /* 2 */
OUTPUT_FIELD_WITH_FIELDS ("IP6", nmc_fields_ip6_config), /* 3 */
OUTPUT_FIELD_WITH_FIELDS ("DHCP6", nmc_fields_dhcp6_config), /* 4 */
OUTPUT_FIELD_WITH_FIELDS ("VPN", nmc_fields_con_active_details_vpn), /* 5 */
{ 0 }
};
#define NMC_FIELDS_CON_ACTIVE_DETAILS_ALL "GENERAL,IP4,DHCP4,IP6,DHCP6,VPN"
@ -780,12 +790,16 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean s
g_assert (print_settings_array);
/* Main header */
nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_connection_get_id (connection));
nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_SETTINGS_NAMES_ALL,
nmc_fields_settings_names, FALSE, NULL, NULL);
{
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
nmc_fields_settings_names[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
print_required_fields (nmc, nmc_fields_settings_names);
out.print_fields.header_name = (char *) construct_header_name (base_hdr, nm_connection_get_id (connection));
out.print_fields.indices = parse_output_fields (NMC_FIELDS_SETTINGS_NAMES_ALL,
nmc_fields_settings_names, FALSE, NULL, NULL);
nmc_fields_settings_names[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
print_required_fields (&nmc->nmc_config, &out.print_fields, nmc_fields_settings_names);
}
/* Loop through the required settings and print them. */
for (i = 0; i < print_settings_array->len; i++) {
@ -793,19 +807,15 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc, gboolean s
int section_idx = g_array_index (print_settings_array, int, i);
const char *prop_name = (const char *) g_ptr_array_index (prop_array, i);
if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output)
if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
g_print ("\n"); /* Empty line */
was_output = FALSE;
/* Remove any previous data */
nmc_empty_output_fields (nmc);
setting = nm_connection_get_setting_by_name (connection, nmc_fields_settings_names[section_idx].name);
if (setting) {
setting_details (setting, nmc, prop_name, secrets);
was_output = TRUE;
continue;
}
}
@ -907,7 +917,7 @@ nmc_active_connection_state_to_color (NMActiveConnectionState state, NmcTermColo
}
static void
fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_only)
fill_output_connection (NMConnection *connection, NMClient *client, GPtrArray *output_data, gboolean active_only)
{
NMSettingConnection *s_con;
guint64 timestamp;
@ -926,7 +936,7 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
ac = get_ac_for_connection (nm_client_get_active_connections (nmc->client), connection);
ac = get_ac_for_connection (nm_client_get_active_connections (client), connection);
if (active_only && !ac)
return;
@ -970,11 +980,11 @@ fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_on
set_val_strc (arr, 12, ac_path);
set_val_strc (arr, 13, nm_setting_connection_get_slave_type (s_con));
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (output_data, arr);
}
static void
fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
fill_output_connection_for_invisible (NMActiveConnection *ac, GPtrArray *output_data)
{
NmcOutputField *arr;
const char *ac_path = NULL;
@ -1007,12 +1017,12 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
set_val_color_fmt_all (arr, NMC_TERM_FORMAT_DIM);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (output_data, arr);
}
static void
fill_output_active_connection (NMActiveConnection *active,
NmCli *nmc,
GPtrArray *output_data,
gboolean with_group,
guint32 o_flags)
{
@ -1079,7 +1089,7 @@ fill_output_active_connection (NMActiveConnection *active,
set_val_strc (arr, 12-idx_start, master ? nm_object_get_path (NM_OBJECT (master)) : NULL);
set_val_strc (arr, 13-idx_start, s_con ? nm_setting_connection_get_slave_type (s_con) : NULL);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (output_data, arr);
g_string_free (dev_str, FALSE);
}
@ -1207,40 +1217,44 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
g_assert (print_groups);
/* Main header */
nmc->print_fields.header_name = (char *) construct_header_name (base_hdr, nm_active_connection_get_uuid (acon));
nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_CON_ACTIVE_DETAILS_ALL,
nmc_fields_con_active_details_groups, FALSE, NULL, NULL);
{
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
nmc_fields_con_active_details_groups[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
print_required_fields (nmc, nmc_fields_con_active_details_groups);
out.print_fields.header_name = (char *) construct_header_name (base_hdr, nm_active_connection_get_uuid (acon));
out.print_fields.indices = parse_output_fields (NMC_FIELDS_CON_ACTIVE_DETAILS_ALL,
nmc_fields_con_active_details_groups, FALSE, NULL, NULL);
nmc_fields_con_active_details_groups[0].flags = NMC_OF_FLAG_MAIN_HEADER_ONLY;
print_required_fields (&nmc->nmc_config, &out.print_fields, nmc_fields_con_active_details_groups);
}
/* Loop through the groups and print them. */
for (i = 0; i < print_groups->len; i++) {
int group_idx = g_array_index (print_groups, int, i);
char *group_fld = (char *) g_ptr_array_index (group_fields, i);
if (nmc->print_output != NMC_PRINT_TERSE && !nmc->multiline_output && was_output)
if (nmc->nmc_config.print_output != NMC_PRINT_TERSE && !nmc->nmc_config.multiline_output && was_output)
g_print ("\n"); /* Empty line */
was_output = FALSE;
/* Remove any previous data */
nmc_empty_output_fields (nmc);
/* GENERAL */
if (strcasecmp (nmc_fields_con_active_details_groups[group_idx].name, nmc_fields_con_active_details_groups[0].name) == 0) {
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
/* Add field names */
tmpl = nmc_fields_con_active_details_general;
tmpl_len = sizeof (nmc_fields_con_active_details_general);
nmc->print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_GENERAL_ALL,
tmpl, FALSE, NULL, NULL);
out.print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_GENERAL_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
/* Fill in values */
fill_output_active_connection (acon, nmc, TRUE, NMC_OF_FLAG_SECTION_PREFIX);
fill_output_active_connection (acon, out.output_data, TRUE, NMC_OF_FLAG_SECTION_PREFIX);
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
was_output = TRUE;
}
@ -1250,7 +1264,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
gboolean b1 = FALSE;
NMIPConfig *cfg4 = nm_active_connection_get_ip4_config (acon);
b1 = print_ip4_config (cfg4, nmc, "IP4", group_fld);
b1 = print_ip4_config (cfg4, &nmc->nmc_config, "IP4", group_fld);
was_output = was_output || b1;
}
@ -1259,7 +1273,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, "DHCP4", group_fld);
b1 = print_dhcp4_config (dhcp4, &nmc->nmc_config, "DHCP4", group_fld);
was_output = was_output || b1;
}
@ -1268,7 +1282,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
gboolean b1 = FALSE;
NMIPConfig *cfg6 = nm_active_connection_get_ip6_config (acon);
b1 = print_ip6_config (cfg6, nmc, "IP6", group_fld);
b1 = print_ip6_config (cfg6, &nmc->nmc_config, "IP6", group_fld);
was_output = was_output || b1;
}
@ -1277,7 +1291,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, "DHCP6", group_fld);
b1 = print_dhcp6_config (dhcp6, &nmc->nmc_config, "DHCP6", group_fld);
was_output = was_output || b1;
}
@ -1293,6 +1307,7 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
const char *username = NULL;
char **vpn_data_array = NULL;
guint32 items_num;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
con = NM_CONNECTION (nm_active_connection_get_connection (acon));
@ -1301,10 +1316,10 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
tmpl = nmc_fields_con_active_details_vpn;
tmpl_len = sizeof (nmc_fields_con_active_details_vpn);
nmc->print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_VPN_ALL,
tmpl, FALSE, NULL, NULL);
out.print_fields.indices = parse_output_fields (group_fld ? group_fld : NMC_FIELDS_CON_ACTIVE_DETAILS_VPN_ALL,
tmpl, FALSE, NULL, NULL);
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
s_vpn = nm_connection_get_setting_vpn (con);
if (s_vpn) {
@ -1337,9 +1352,10 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
set_val_str (arr, 4, banner_str);
set_val_str (arr, 5, vpn_state_str);
set_val_arr (arr, 6, vpn_data_array);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
was_output = TRUE;
}
}
@ -1784,6 +1800,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
char *fields_common = NMC_FIELDS_CON_SHOW_COMMON;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (nmc->complete)
goto finish;
@ -1797,31 +1814,32 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
tmpl = nmc_fields_con_show;
tmpl_len = sizeof (nmc_fields_con_show);
nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &err);
out.print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &err);
if (err)
goto finish;
/* Add headers */
nmc->print_fields.header_name = active_only ? _("NetworkManager active profiles") :
out.print_fields.header_name = active_only ? _("NetworkManager active profiles") :
_("NetworkManager connection profiles");
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
/* There might be active connections not present in connection list
* (e.g. private connections of a different user). Show them as well. */
invisibles = get_invisible_active_connections (nmc);
for (i = 0; i < invisibles->len; i++)
fill_output_connection_for_invisible (invisibles->pdata[i], nmc);
fill_output_connection_for_invisible (invisibles->pdata[i], out.output_data);
g_ptr_array_free (invisibles, TRUE);
/* Sort the connections and fill the output data */
connections = nm_client_get_connections (nmc->client);
sorted_cons = sort_connections (connections, nmc, order);
for (i = 0; i < sorted_cons->len; i++)
fill_output_connection (sorted_cons->pdata[i], nmc, active_only);
fill_output_connection (sorted_cons->pdata[i], nmc->client, out.output_data, active_only);
g_ptr_array_free (sorted_cons, TRUE);
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
} else {
gboolean new_line = FALSE;
gboolean without_fields = (nmc->required_fields == NULL);
@ -1830,7 +1848,7 @@ do_connections_show (NmCli *nmc, int argc, char **argv)
/* multiline mode is default for 'connection show <ID>' */
if (!nmc->mode_specified)
nmc->multiline_output = TRUE;
nmc->nmc_config_mutable.multiline_output = TRUE;
/* Split required fields into the settings and active ones. */
if (!split_required_fields_for_con_show (nmc->required_fields, &profile_flds, &active_flds, &err))
@ -2178,7 +2196,7 @@ check_activated (ActivateConnectionInfo *info)
}
if (ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
nm_object_get_path (NM_OBJECT (active)));
@ -2218,7 +2236,7 @@ check_activated (ActivateConnectionInfo *info)
|| NM_IS_DEVICE_BRIDGE (device))
&& dev_state >= NM_DEVICE_STATE_IP_CONFIG
&& dev_state <= NM_DEVICE_STATE_ACTIVATED) {
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
g_print (_("Connection successfully activated (master waiting for slaves) (D-Bus active path: %s)\n"),
nm_object_get_path (NM_OBJECT (active)));
@ -2348,7 +2366,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
if (nmc->nowait_flag || state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
/* User doesn't want to wait or already activated */
if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
g_print (_("Connection successfully activated (D-Bus active path: %s)\n"),
nm_object_get_path (NM_OBJECT (active)));
@ -2368,7 +2386,7 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
}
/* Start progress indication showing VPN states */
if (nmc->print_output == NMC_PRINT_PRETTY) {
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
if (progress_id)
g_source_remove (progress_id);
progress_id = g_timeout_add (120, progress_active_connection_cb, active);
@ -2656,7 +2674,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
}
/* Start progress indication */
if (nmc->print_output == NMC_PRINT_PRETTY)
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
progress_id = g_timeout_add (120, progress_cb, _("preparing"));
return nmc->return_value;
@ -2691,7 +2709,7 @@ down_active_connection_state_cb (NMActiveConnection *active,
if (nm_active_connection_get_state (active) < NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
return;
if (info->nmc->print_output == NMC_PRINT_PRETTY)
if (info->nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
nmc_terminal_erase_line ();
g_print (_("Connection '%s' successfully deactivated (D-Bus active path: %s)\n"),
nm_active_connection_get_id (active), nm_object_get_path (NM_OBJECT (active)));
@ -3179,6 +3197,7 @@ get_valid_properties_string (const NameItem *array,
{
const NameItem *iter = array;
const NmcOutputField *field_iter;
const NMMetaSettingInfoEditor *setting_info;
const char *prop_name = NULL;
GString *str;
int i, j;
@ -3219,20 +3238,31 @@ get_valid_properties_string (const NameItem *array,
g_assert (nmc_fields_settings_names[j].name);
j++;
}
field_iter = nmc_fields_settings_names[j].group;
field_iter = nmc_fields_settings_names[j].group_list;
setting_info = nmc_fields_settings_names[j].setting_info;
j = 0;
while (field_iter[j].name) {
while (TRUE) {
gchar *new;
const char *arg_name = field_iter[j].name;
const char *arg_name;
if (field_iter) {
arg_name = field_iter[j].name;
if (!arg_name)
break;
} else {
if (j + 1 >= setting_info->properties_num)
break;
arg_name = setting_info->properties[j + 1].property_name;
}
/* If required, expand the alias too */
if (!postfix && iter->alias) {
if (modifier)
g_string_append_c (str, modifier);
new = g_strdup_printf ("%s.%s\n",
iter->alias,
arg_name);
iter->alias,
arg_name);
g_string_append (str, new);
g_free (new);
}
@ -3245,8 +3275,8 @@ get_valid_properties_string (const NameItem *array,
if (modifier)
g_string_append_c (str, modifier);
new = g_strdup_printf ("%s.%s\n",
prop_name,
arg_name);
prop_name,
arg_name);
g_string_append (str, new);
g_free (new);
j++;
@ -5682,27 +5712,24 @@ should_complete_vpn_uuids (const char *prompt, const char *line)
return _get_and_check_property (prompt, line, uuid_properties, NULL, NULL);
}
static const char **
get_allowed_property_values (void)
static const char *const*
get_allowed_property_values (char ***out_to_free)
{
NMSetting *setting;
char *property;
const char **avals = NULL;
gs_unref_object NMSetting *setting = NULL;
gs_free char *property = NULL;
const char *const*avals = NULL;
get_setting_and_property (rl_prompt, rl_line_buffer, &setting, &property);
if (setting && property)
avals = nmc_setting_get_property_allowed_values (setting, property);
if (setting)
g_object_unref (setting);
g_free (property);
avals = nmc_setting_get_property_allowed_values (setting, property, out_to_free);
return avals;
}
static gboolean
should_complete_property_values (const char *prompt, const char *line, gboolean *multi)
{
gs_strfreev char **to_free = NULL;
/* properties allowing multiple values */
const char *multi_props[] = {
/* '802-1x' properties */
@ -5718,10 +5745,9 @@ should_complete_property_values (const char *prompt, const char *line, gboolean
NULL
};
_get_and_check_property (prompt, line, NULL, multi_props, multi);
return get_allowed_property_values () != NULL;
return !!get_allowed_property_values (&to_free);
}
//FIXME: this helper should go to libnm later
static gboolean
_setting_property_is_boolean (NMSetting *setting, const char *property_name)
{
@ -5757,13 +5783,13 @@ should_complete_boolean (const char *prompt, const char *line)
static char *
gen_property_values (const char *text, int state)
{
char *ret = NULL;
const char **avals;
gs_strfreev char **to_free = NULL;
const char *const*avals;
avals = get_allowed_property_values ();
if (avals)
ret = nmc_rl_gen_func_basic (text, state, avals);
return ret;
avals = get_allowed_property_values (&to_free);
if (!avals)
return NULL;
return nmc_rl_gen_func_basic (text, state, avals);
}
/* from readline */
@ -5997,12 +6023,9 @@ save_history_cmds (const char *uuid)
static void
editor_show_connection (NMConnection *connection, NmCli *nmc)
{
nmc->print_output = NMC_PRINT_PRETTY;
nmc->multiline_output = TRUE;
nmc->escape_values = 0;
/* Remove any previous data */
nmc_empty_output_fields (nmc);
nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
nmc->nmc_config_mutable.multiline_output = TRUE;
nmc->nmc_config_mutable.escape_values = 0;
nmc_connection_profile_details (connection, nmc, nmc->editor_show_secrets);
}
@ -6013,12 +6036,9 @@ editor_show_setting (NMSetting *setting, NmCli *nmc)
g_print (_("['%s' setting values]\n"),
nm_setting_get_name (setting));
nmc->print_output = NMC_PRINT_NORMAL;
nmc->multiline_output = TRUE;
nmc->escape_values = 0;
/* Remove any previous data */
nmc_empty_output_fields (nmc);
nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL;
nmc->nmc_config_mutable.multiline_output = TRUE;
nmc->nmc_config_mutable.escape_values = 0;
setting_details (setting, nmc, NULL, nmc->editor_show_secrets);
}
@ -6606,7 +6626,7 @@ property_edit_submenu (NmCli *nmc,
/* Set global variable for use in TAB completion */
nmc_tab_completion.property = prop_name;
prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s.%s> ",
nm_setting_get_name (curr_setting), prop_name);
@ -6639,12 +6659,16 @@ property_edit_submenu (NmCli *nmc,
* single values: : both SET and ADD sets the new value
*/
if (!cmd_property_arg) {
const char **avals = nmc_setting_get_property_allowed_values (curr_setting, prop_name);
gs_strfreev char **to_free = NULL;
const char *const*avals;
avals = nmc_setting_get_property_allowed_values (curr_setting, prop_name, &to_free);
if (avals) {
char *avals_str = nmc_util_strv_for_display (avals, FALSE);
gs_free char *avals_str = NULL;
avals_str = nmc_util_strv_for_display (avals, FALSE);
g_print (_("Allowed values for '%s' property: %s\n"),
prop_name, avals_str);
g_free (avals_str);
}
prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name);
} else
@ -6938,14 +6962,14 @@ typedef struct {
} NmcEditorMenuContext;
static void
menu_switch_to_level0 (NmCli *nmc,
menu_switch_to_level0 (NmcColorOption color_option,
NmcEditorMenuContext *menu_ctx,
const char *prompt,
NmcTermColor prompt_color)
{
menu_ctx->level = 0;
g_free (menu_ctx->main_prompt);
menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
menu_ctx->curr_setting = NULL;
g_strfreev (menu_ctx->valid_props);
menu_ctx->valid_props = NULL;
@ -6954,7 +6978,7 @@ menu_switch_to_level0 (NmCli *nmc,
}
static void
menu_switch_to_level1 (NmCli *nmc,
menu_switch_to_level1 (NmcColorOption color_option,
NmcEditorMenuContext *menu_ctx,
NMSetting *setting,
const char *setting_name,
@ -6962,7 +6986,7 @@ menu_switch_to_level1 (NmCli *nmc,
{
menu_ctx->level = 1;
g_free (menu_ctx->main_prompt);
menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx->main_prompt = nmc_colorize (color_option, prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ", setting_name);
menu_ctx->curr_setting = setting;
g_strfreev (menu_ctx->valid_props);
@ -7008,7 +7032,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
g_print (_("You may edit the following settings: %s\n"), valid_settings_str);
menu_ctx.level = 0;
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
menu_ctx.curr_setting = NULL;
menu_ctx.valid_props = NULL;
@ -7049,9 +7073,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
/* Set property value */
if (!cmd_arg) {
if (menu_ctx.level == 1) {
gs_strfreev char **avals_to_free = NULL;
gs_free char *prop_val_user = NULL;
const char *prop_name;
char *prop_val_user = NULL;
const char **avals;
const char *const*avals;
GError *tmp_err = NULL;
prop_name = ask_check_property (cmd_arg,
@ -7060,12 +7085,13 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
if (!prop_name)
break;
avals = nmc_setting_get_property_allowed_values (menu_ctx.curr_setting, prop_name);
avals = nmc_setting_get_property_allowed_values (menu_ctx.curr_setting, prop_name, &avals_to_free);
if (avals) {
char *avals_str = nmc_util_strv_for_display (avals, FALSE);
gs_free char *avals_str = NULL;
avals_str = nmc_util_strv_for_display (avals, FALSE);
g_print (_("Allowed values for '%s' property: %s\n"),
prop_name, avals_str);
g_free (avals_str);
}
prop_val_user = nmc_readline (_("Enter '%s' value: "), prop_name);
@ -7118,12 +7144,16 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
/* Ask for value */
if (!cmd_arg_v) {
const char **avals = nmc_setting_get_property_allowed_values (ss, prop_name);
gs_strfreev char **avals_to_free = NULL;
const char *const*avals;
avals = nmc_setting_get_property_allowed_values (ss, prop_name, &avals_to_free);
if (avals) {
char *avals_str = nmc_util_strv_for_display (avals, FALSE);
gs_free char *avals_str = NULL;
avals_str = nmc_util_strv_for_display (avals, FALSE);
g_print (_("Allowed values for '%s' property: %s\n"),
prop_name, avals_str);
g_free (avals_str);
}
cmd_arg_v = nmc_readline (_("Enter '%s' value: "), prop_name);
}
@ -7180,7 +7210,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, &menu_ctx, setting, setting_name, nmc->editor_prompt_color);
menu_switch_to_level1 (nmc->nmc_config.use_colors, &menu_ctx, setting, setting_name, nmc->editor_prompt_color);
if (!cmd_arg_s) {
g_print (_("You may edit the following properties: %s\n"), menu_ctx.valid_props_str);
@ -7261,7 +7291,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, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
} else {
@ -7287,7 +7317,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, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
} else
@ -7599,7 +7629,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
nmc->nowait_flag = FALSE;
nmc->should_wait++;
nmc->print_output = NMC_PRINT_PRETTY;
nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
if (!nmc_activate_connection (nmc, NM_CONNECTION (rem_con), ifname, ap_nsp, ap_nsp, NULL,
activate_connection_editor_cb, &tmp_err)) {
g_print (_("Error: Cannot activate connection: %s.\n"), tmp_err->message);
@ -7638,7 +7668,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, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc->nmc_config.use_colors, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
break;
@ -7684,10 +7714,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
nmc->editor_prompt_color = color;
g_free (menu_ctx.main_prompt);
if (menu_ctx.level == 0)
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
else
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc->nmc_config.use_colors, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ",
nm_setting_get_name (menu_ctx.curr_setting));
}
@ -8024,7 +8054,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
}
/* nmcli runs the editor */
nmc->in_editor = TRUE;
nmc->nmc_config_mutable.in_editor = TRUE;
g_print ("\n");
g_print (_("===| nmcli interactive connection editor |==="));
@ -8077,7 +8107,7 @@ modify_connection_cb (GObject *connection,
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
} else {
if (nmc->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)));

File diff suppressed because it is too large Load diff

View file

@ -22,31 +22,35 @@
#include <string.h>
#include <stdlib.h>
#include "nm-common-macros.h"
#include "nm-client-utils.h"
#include "polkit-agent.h"
#include "utils.h"
#include "common.h"
#include "general.h"
#include "common.h"
#include "nm-common-macros.h"
#include "devices.h"
#include "connections.h"
#define OUTPUT_FIELD_WITH_NAME(n) { .name = N_ (n), }
/* Available fields for 'general status' */
static NmcOutputField nmc_fields_nm_status[] = {
{"RUNNING", N_("RUNNING")}, /* 0 */
{"VERSION", N_("VERSION")}, /* 1 */
{"STATE", N_("STATE")}, /* 2 */
{"STARTUP", N_("STARTUP")}, /* 3 */
{"CONNECTIVITY", N_("CONNECTIVITY")}, /* 4 */
{"NETWORKING", N_("NETWORKING")}, /* 5 */
{"WIFI-HW", N_("WIFI-HW")}, /* 6 */
{"WIFI", N_("WIFI")}, /* 7 */
{"WWAN-HW", N_("WWAN-HW")}, /* 8 */
{"WWAN", N_("WWAN")}, /* 9 */
{"WIMAX-HW", N_("WIMAX-HW")}, /* 10 */
{"WIMAX", N_("WIMAX")}, /* 11 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("RUNNING"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("VERSION"), /* 1 */
OUTPUT_FIELD_WITH_NAME ("STATE"), /* 2 */
OUTPUT_FIELD_WITH_NAME ("STARTUP"), /* 3 */
OUTPUT_FIELD_WITH_NAME ("CONNECTIVITY"), /* 4 */
OUTPUT_FIELD_WITH_NAME ("NETWORKING"), /* 5 */
OUTPUT_FIELD_WITH_NAME ("WIFI-HW"), /* 6 */
OUTPUT_FIELD_WITH_NAME ("WIFI"), /* 7 */
OUTPUT_FIELD_WITH_NAME ("WWAN-HW"), /* 8 */
OUTPUT_FIELD_WITH_NAME ("WWAN"), /* 9 */
OUTPUT_FIELD_WITH_NAME ("WIMAX-HW"), /* 10 */
OUTPUT_FIELD_WITH_NAME ("WIMAX"), /* 11 */
{ 0 }
};
#define NMC_FIELDS_NM_STATUS_ALL "RUNNING,VERSION,STATE,STARTUP,CONNECTIVITY,NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
#define NMC_FIELDS_NM_STATUS_SWITCH "NETWORKING,WIFI-HW,WIFI,WWAN-HW,WWAN"
@ -61,18 +65,18 @@ static NmcOutputField nmc_fields_nm_status[] = {
/* Available fields for 'general permissions' */
static NmcOutputField nmc_fields_nm_permissions[] = {
{"PERMISSION", N_("PERMISSION")}, /* 0 */
{"VALUE", N_("VALUE")}, /* 1 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("PERMISSION"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("VALUE"), /* 1 */
{ 0 }
};
#define NMC_FIELDS_NM_PERMISSIONS_ALL "PERMISSION,VALUE"
#define NMC_FIELDS_NM_PERMISSIONS_COMMON "PERMISSION,VALUE"
/* Available fields for 'general logging' */
static NmcOutputField nmc_fields_nm_logging[] = {
{"LEVEL", N_("LEVEL")}, /* 0 */
{"DOMAINS", N_("DOMAINS")}, /* 1 */
{NULL, NULL}
OUTPUT_FIELD_WITH_NAME ("LEVEL"), /* 0 */
OUTPUT_FIELD_WITH_NAME ("DOMAINS"), /* 1 */
{ 0 }
};
#define NMC_FIELDS_NM_LOGGING_ALL "LEVEL,DOMAINS"
#define NMC_FIELDS_NM_LOGGING_COMMON "LEVEL,DOMAINS"
@ -321,6 +325,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
const char *fields_common = print_flds ? print_flds : NMC_FIELDS_NM_STATUS_COMMON;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
@ -331,7 +336,7 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
tmpl = nmc_fields_nm_status;
tmpl_len = sizeof (nmc_fields_nm_status);
nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
out.print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
if (error) {
g_string_printf (nmc->return_text, _("Error: only these fields are allowed: %s"), fields_all);
@ -349,9 +354,9 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
wwan_hw_enabled = nm_client_wwan_hardware_get_enabled (nmc->client);
wwan_enabled = nm_client_wwan_get_enabled (nmc->client);
nmc->print_fields.header_name = pretty_header_name ? (char *) pretty_header_name : _("NetworkManager status");
out.print_fields.header_name = pretty_header_name ? (char *) pretty_header_name : _("NetworkManager status");
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
set_val_strc (arr, 0, _("running"));
@ -375,9 +380,10 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
arr[8].color = wwan_hw_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
arr[9].color = wwan_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
return TRUE;
}
@ -468,6 +474,7 @@ print_permissions (void *user_data)
const char *fields_common = NMC_FIELDS_NM_PERMISSIONS_COMMON;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
@ -478,7 +485,7 @@ print_permissions (void *user_data)
tmpl = nmc_fields_nm_permissions;
tmpl_len = sizeof (nmc_fields_nm_permissions);
nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
out.print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
if (error) {
g_string_printf (nmc->return_text, _("Error: 'general permissions': %s"), error->message);
@ -487,9 +494,9 @@ print_permissions (void *user_data)
return FALSE;
}
nmc->print_fields.header_name = _("NetworkManager permissions");
out.print_fields.header_name = _("NetworkManager permissions");
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
@ -498,9 +505,10 @@ print_permissions (void *user_data)
arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
set_val_strc (arr, 0, permission_to_string (perm));
set_val_strc (arr, 1, permission_result_to_string (perm_result));
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
}
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
quit ();
return G_SOURCE_REMOVE;
@ -577,6 +585,7 @@ show_general_logging (NmCli *nmc)
const char *fields_common = NMC_FIELDS_NM_LOGGING_COMMON;
NmcOutputField *tmpl, *arr;
size_t tmpl_len;
NMC_OUTPUT_DATA_DEFINE_SCOPED (out);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
@ -587,7 +596,7 @@ show_general_logging (NmCli *nmc)
tmpl = nmc_fields_nm_logging;
tmpl_len = sizeof (nmc_fields_nm_logging);
nmc->print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
out.print_fields.indices = parse_output_fields (fields_str, tmpl, FALSE, NULL, &error);
if (error) {
g_string_printf (nmc->return_text, _("Error: 'general logging': %s"), error->message);
@ -604,16 +613,17 @@ show_general_logging (NmCli *nmc)
return FALSE;
}
nmc->print_fields.header_name = _("NetworkManager logging");
out.print_fields.header_name = _("NetworkManager logging");
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_MAIN_HEADER_ADD | NMC_OF_FLAG_FIELD_NAMES);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
arr = nmc_dup_fields_array (tmpl, tmpl_len, 0);
set_val_str (arr, 0, level);
set_val_str (arr, 1, domains);
g_ptr_array_add (nmc->output_data, arr);
g_ptr_array_add (out.output_data, arr);
print_data (nmc); /* Print all data */
print_data_prepare_width (out.output_data);
print_data (&nmc->nmc_config, &out);
return TRUE;
}
@ -782,8 +792,8 @@ nmc_switch_show (NmCli *nmc, const char *switch_name, const char *header)
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE;
}
if (nmc->print_output == NMC_PRINT_NORMAL)
nmc->print_output = NMC_PRINT_TERSE;
if (nmc->nmc_config.print_output == NMC_PRINT_NORMAL)
nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
if (!nmc->required_fields)
nmc->required_fields = g_strdup (switch_name);
@ -1007,7 +1017,7 @@ networkmanager_running (NMClient *client, GParamSpec *param, NmCli *nmc)
char *str;
running = nm_client_get_nm_running (client);
str = nmc_colorize (nmc,
str = nmc_colorize (nmc->nmc_config.use_colors,
running ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED,
NMC_TERM_FORMAT_NORMAL,
running ? _("NetworkManager has started") : _("NetworkManager has stopped"));
@ -1049,7 +1059,7 @@ client_connectivity (NMClient *client, GParamSpec *param, NmCli *nmc)
char *str;
g_object_get (client, NM_CLIENT_CONNECTIVITY, &connectivity, NULL);
str = nmc_colorize (nmc, connectivity_to_color (connectivity), NMC_TERM_FORMAT_NORMAL,
str = nmc_colorize (nmc->nmc_config.use_colors, connectivity_to_color (connectivity), NMC_TERM_FORMAT_NORMAL,
_("Connectivity is now '%s'\n"), nm_connectivity_to_string (connectivity));
g_print ("%s", str);
g_free (str);
@ -1062,7 +1072,7 @@ client_state (NMClient *client, GParamSpec *param, NmCli *nmc)
char *str;
g_object_get (client, NM_CLIENT_STATE, &state, NULL);
str = nmc_colorize (nmc, state_to_color (state), NMC_TERM_FORMAT_NORMAL,
str = nmc_colorize (nmc->nmc_config.use_colors, state_to_color (state), NMC_TERM_FORMAT_NORMAL,
_("Networkmanager is now in the '%s' state\n"),
nm_state_to_string (state));
g_print ("%s", str);
@ -1106,12 +1116,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_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("fw missing"));
tmp = nmc_colorize (nmc->nmc_config.use_colors, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("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_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("plugin missing"));
tmp = nmc_colorize (nmc->nmc_config.use_colors, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL, _("plugin missing"));
g_string_append_printf (outbuf, "%s, ", tmp);
g_free (tmp);
}
@ -1232,7 +1242,7 @@ do_overview (NmCli *nmc, int argc, char **argv)
state = nm_active_connection_get_state (ac);
nmc_active_connection_state_to_color (state, &color);
tmp = nmc_colorize (nmc, color, NMC_TERM_FORMAT_NORMAL, _("%s VPN connection"),
tmp = nmc_colorize (nmc->nmc_config.use_colors, color, NMC_TERM_FORMAT_NORMAL, _("%s VPN connection"),
nm_active_connection_get_id (ac));
g_print ("%s\n", tmp);
g_free (tmp);
@ -1250,7 +1260,7 @@ do_overview (NmCli *nmc, int argc, char **argv)
state = nm_device_get_state (devices[i]);
nmc_device_state_to_color (state, &color, &color_fmt);
tmp = nmc_colorize (nmc, color, color_fmt, "%s: %s%s%s",
tmp = nmc_colorize (nmc->nmc_config.use_colors, color, color_fmt, "%s: %s%s%s",
nm_device_get_iface (devices[i]),
nmc_device_state_to_string (state),
ac ? " to " : "",
@ -1332,7 +1342,7 @@ do_monitor (NmCli *nmc, int argc, char **argv)
if (!nm_client_get_nm_running (nmc->client)) {
char *str;
str = nmc_colorize (nmc, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL,
str = nmc_colorize (nmc->nmc_config.use_colors, NMC_TERM_COLOR_RED, NMC_TERM_FORMAT_NORMAL,
_("Networkmanager is not running (waiting for it)\n"));
g_print ("%s", str);
g_free (str);

View file

@ -32,6 +32,8 @@
#include <readline/readline.h>
#include <readline/history.h>
#include "nm-client-utils.h"
#include "polkit-agent.h"
#include "nmcli.h"
#include "utils.h"
@ -66,7 +68,22 @@ struct termios termios_orig;
NM_CACHED_QUARK_FCN ("nmcli-error-quark", nmcli_error_quark)
static void
complete_field (GHashTable *h, const char *setting, NmcOutputField field[])
complete_field_setting (GHashTable *h, NMMetaSettingType setting_type)
{
const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[setting_type];
guint i;
for (i = 0; i < setting_info->properties_num; i++) {
if (setting_info->properties[i].is_name)
continue;
g_hash_table_add (h, g_strdup_printf ("%s.%s",
setting_info->general->setting_name,
setting_info->properties[i].property_name));
}
}
static void
complete_field (GHashTable *h, const char *setting, const NmcOutputField *field)
{
int i;
@ -100,7 +117,7 @@ complete_one (gpointer key, gpointer value, gpointer user_data)
static void
complete_fields (const char *prefix)
{
guint i;
GHashTable *h;
h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@ -130,35 +147,8 @@ complete_fields (const char *prefix)
complete_field (h, NULL, nmc_fields_dev_show_sections);
complete_field (h, NULL, nmc_fields_dev_lldp_list);
complete_field (h, "connection", nmc_fields_setting_connection);
complete_field (h, "802-3-ethernet", nmc_fields_setting_wired);
complete_field (h, "802-1x", nmc_fields_setting_8021X);
complete_field (h, "802-11-wireless", nmc_fields_setting_wireless);
complete_field (h, "802-11-wireless-security", nmc_fields_setting_wireless_security);
complete_field (h, "ipv4", nmc_fields_setting_ip4_config);
complete_field (h, "ipv6", nmc_fields_setting_ip6_config);
complete_field (h, "serial", nmc_fields_setting_serial);
complete_field (h, "ppp", nmc_fields_setting_ppp);
complete_field (h, "pppoe", nmc_fields_setting_pppoe);
complete_field (h, "adsl", nmc_fields_setting_adsl);
complete_field (h, "gsm", nmc_fields_setting_gsm);
complete_field (h, "cdma", nmc_fields_setting_cdma);
complete_field (h, "bluetooth", nmc_fields_setting_bluetooth);
complete_field (h, "802-11-olpc-mesh", nmc_fields_setting_olpc_mesh);
complete_field (h, "vpn", nmc_fields_setting_vpn);
complete_field (h, "wimax", nmc_fields_setting_wimax);
complete_field (h, "infiniband", nmc_fields_setting_infiniband);
complete_field (h, "bond", nmc_fields_setting_bond);
complete_field (h, "vlan", nmc_fields_setting_vlan);
complete_field (h, "bridge", nmc_fields_setting_bridge);
complete_field (h, "bridge-port", nmc_fields_setting_bridge_port);
complete_field (h, "team", nmc_fields_setting_team);
complete_field (h, "team-port", nmc_fields_setting_team_port);
complete_field (h, "dcb", nmc_fields_setting_dcb);
complete_field (h, "tun", nmc_fields_setting_tun);
complete_field (h, "ip-tunnel", nmc_fields_setting_ip_tunnel);
complete_field (h, "macvlan", nmc_fields_setting_macvlan);
complete_field (h, "vxlan", nmc_fields_setting_vxlan);
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++)
complete_field_setting (h, i);
g_hash_table_foreach (h, complete_one, (gpointer) prefix);
g_hash_table_destroy (h);
@ -245,31 +235,31 @@ process_command_line (NmCli *nmc, int argc, char **argv)
}
if (matches (opt, "-terse")) {
if (nmc->print_output == NMC_PRINT_TERSE) {
if (nmc->nmc_config.print_output == NMC_PRINT_TERSE) {
g_string_printf (nmc->return_text, _("Error: Option '--terse' is specified the second time."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE;
}
else if (nmc->print_output == NMC_PRINT_PRETTY) {
else if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
g_string_printf (nmc->return_text, _("Error: Option '--terse' is mutually exclusive with '--pretty'."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE;
}
else
nmc->print_output = NMC_PRINT_TERSE;
nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE;
} else if (matches (opt, "-pretty")) {
if (nmc->print_output == NMC_PRINT_PRETTY) {
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) {
g_string_printf (nmc->return_text, _("Error: Option '--pretty' is specified the second time."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE;
}
else if (nmc->print_output == NMC_PRINT_TERSE) {
else if (nmc->nmc_config.print_output == NMC_PRINT_TERSE) {
g_string_printf (nmc->return_text, _("Error: Option '--pretty' is mutually exclusive with '--terse'."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return FALSE;
}
else
nmc->print_output = NMC_PRINT_PRETTY;
nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY;
} else if (matches (opt, "-mode")) {
nmc->mode_specified = TRUE;
argc--;
@ -282,9 +272,9 @@ process_command_line (NmCli *nmc, int argc, char **argv)
if (argc == 1 && nmc->complete)
nmc_complete_strings (argv[0], "tabular", "multiline", NULL);
if (matches (argv[0], "tabular"))
nmc->multiline_output = FALSE;
nmc->nmc_config_mutable.multiline_output = FALSE;
else if (matches (argv[0], "multiline"))
nmc->multiline_output = TRUE;
nmc->nmc_config_mutable.multiline_output = TRUE;
else {
g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
@ -301,11 +291,11 @@ process_command_line (NmCli *nmc, int argc, char **argv)
if (argc == 1 && nmc->complete)
nmc_complete_strings (argv[0], "yes", "no", "auto", NULL);
if (matches (argv[0], "auto"))
nmc->use_colors = NMC_USE_COLOR_AUTO;
nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO;
else if (matches (argv[0], "yes"))
nmc->use_colors = NMC_USE_COLOR_YES;
nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_YES;
else if (matches (argv[0], "no"))
nmc->use_colors = NMC_USE_COLOR_NO;
nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_NO;
else {
g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
@ -322,9 +312,9 @@ process_command_line (NmCli *nmc, int argc, char **argv)
if (argc == 1 && nmc->complete)
nmc_complete_strings (argv[0], "yes", "no", NULL);
if (matches (argv[0], "yes"))
nmc->escape_values = TRUE;
nmc->nmc_config_mutable.escape_values = TRUE;
else if (matches (argv[0], "no"))
nmc->escape_values = FALSE;
nmc->nmc_config_mutable.escape_values = FALSE;
else {
g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
@ -352,7 +342,7 @@ process_command_line (NmCli *nmc, int argc, char **argv)
if (argc == 1 && nmc->complete)
complete_fields (argv[0]);
nmc->required_fields = g_strdup (argv[0]);
nmc->print_output = NMC_PRINT_TERSE;
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
* before the "-g <field>" option (-g may be still more practical and easy to remember than -t -f).
@ -545,18 +535,16 @@ nmc_init (NmCli *nmc)
nmc->should_wait = 0;
nmc->nowait_flag = TRUE;
nmc->print_output = NMC_PRINT_NORMAL;
nmc->multiline_output = FALSE;
nmc->nmc_config_mutable.print_output = NMC_PRINT_NORMAL;
nmc->nmc_config_mutable.multiline_output = FALSE;
nmc->mode_specified = FALSE;
nmc->escape_values = TRUE;
nmc->nmc_config_mutable.escape_values = TRUE;
nmc->required_fields = NULL;
nmc->output_data = g_ptr_array_new_full (20, g_free);
memset (&nmc->print_fields, '\0', sizeof (NmcPrintFields));
nmc->ask = FALSE;
nmc->complete = FALSE;
nmc->show_secrets = FALSE;
nmc->use_colors = NMC_USE_COLOR_AUTO;
nmc->in_editor = FALSE;
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_show_secrets = FALSE;
@ -579,8 +567,6 @@ nmc_cleanup (NmCli *nmc)
g_hash_table_destroy (nmc->pwds_hash);
g_free (nmc->required_fields);
nmc_empty_output_fields (nmc);
g_ptr_array_unref (nmc->output_data);
nmc_polkit_agent_fini (nmc);
}

View file

@ -104,17 +104,26 @@ typedef enum {
#define NMC_OF_FLAG_MAIN_HEADER_ADD 0x00000004 /* Print main header in addition to values/field names */
#define NMC_OF_FLAG_MAIN_HEADER_ONLY 0x00000008 /* Print main header only */
struct _NMMetaSettingInfoEditor;
typedef struct _NmcOutputField {
const char *name; /* Field's name */
const char *name_l10n; /* Field's name for translation */
int width; /* Width in screen columns */
struct _NmcOutputField *group; /* Points to an array with available section field names if this is a section (group) field */
const struct _NmcOutputField *group_list; /* Points to an array with available section field names if this is a section (group) field */
void *value; /* Value of current field - char* or char** (NULL-terminated array) */
gboolean value_is_array; /* Whether value is char** instead of char* */
gboolean free_value; /* Whether to free the value */
guint32 flags; /* Flags - whether and how to print values/field names/headers */
NmcTermColor color; /* Use this color to print value */
NmcTermFormat color_fmt; /* Use this terminal format to print value */
/* in a very particular case NmcOutputField is used in combination with
* the @group_list above. That list will go away (and the entire NmcOutputField
* should separate formatting-options, setting-metadata and output.
*
* For now, hack around that by alternatively providing a @setting_info instead
* of @group_list. */
const struct _NMMetaSettingInfoEditor *setting_info;
} NmcOutputField;
typedef struct {
@ -129,6 +138,19 @@ typedef enum {
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 multiline_output; /* Multiline output instead of default tabular */
gboolean escape_values; /* Whether to escape ':' and '\' in terse tabular mode */
gboolean in_editor; /* Whether running the editor - nmcli con edit' */
} NmcConfig;
typedef struct _NmcOutputData {
GPtrArray *output_data; /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
NmcPrintFields print_fields; /* Structure with field indices to print */
} NmcOutputData;
/* NmCli - main structure */
typedef struct _NmCli {
NMClient *client; /* Pointer to NMClient of libnm */
@ -144,18 +166,15 @@ typedef struct _NmCli {
int should_wait; /* Semaphore indicating whether nmcli should not end or not yet */
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */
NMCPrintOutput print_output; /* Output mode */
gboolean multiline_output; /* Multiline output instead of default tabular */
gboolean mode_specified; /* Whether tabular/multiline mode was specified via '--mode' option */
NmcColorOption use_colors; /* Whether to use colors for output: option '--color' */
gboolean escape_values; /* Whether to escape ':' and '\' in terse tabular mode */
union {
const NmcConfig nmc_config;
NmcConfig nmc_config_mutable;
};
char *required_fields; /* Required fields in output: '--fields' option */
GPtrArray *output_data; /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */
NmcPrintFields print_fields; /* Structure with field indices to print */
gboolean ask; /* Ask for missing parameters: option '--ask' */
gboolean complete; /* Autocomplete the command line */
gboolean show_secrets; /* Whether to display secrets (both input and output): option '--show-secrets' */
gboolean in_editor; /* Whether running the editor - nmcli con edit' */
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' */
gboolean editor_show_secrets; /* Whether to display secrets in the editor' */
@ -173,4 +192,11 @@ void nmc_clear_sigint (void);
void nmc_set_sigquit_internal (void);
void nmc_exit (void);
void nmc_empty_output_fields (NmcOutputData *output_data);
#define NMC_OUTPUT_DATA_DEFINE_SCOPED(out) \
nm_auto (nmc_empty_output_fields) NmcOutputData out = { \
.output_data = g_ptr_array_new_full (20, g_free), \
}
#endif /* NMC_NMCLI_H */

File diff suppressed because it is too large Load diff

View file

@ -20,13 +20,13 @@
#ifndef NMC_SETTINGS_H
#define NMC_SETTINGS_H
#include "nm-meta-setting.h"
#include "nm-meta-setting-desc.h"
#include "nmcli.h"
#include "utils.h"
/* --- Functions --- */
void nmc_properties_init (void);
void nmc_properties_cleanup (void);
/*****************************************************************************/
NMSetting *nmc_setting_new_for_name (const char *name);
void nmc_setting_custom_init (NMSetting *setting);
@ -38,7 +38,7 @@ void nmc_setting_connection_connect_handlers (NMSettingConnection *setting, NMCo
char **nmc_setting_get_valid_properties (NMSetting *setting);
char *nmc_setting_get_property_desc (NMSetting *setting, const char *prop);
const char **nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop);
const char *const*nmc_setting_get_property_allowed_values (NMSetting *setting, const char *prop, char ***out_to_free);
char *nmc_setting_get_property (NMSetting *setting,
const char *prop,
GError **error);
@ -64,37 +64,4 @@ gboolean nmc_property_set_gvalue (NMSetting *setting, const char *prop, GValue *
gboolean setting_details (NMSetting *setting, NmCli *nmc, const char *one_prop, gboolean secrets);
extern NmcOutputField nmc_fields_setting_connection[];
extern NmcOutputField nmc_fields_setting_wired[];
extern NmcOutputField nmc_fields_setting_8021X[];
extern NmcOutputField nmc_fields_setting_wireless[];
extern NmcOutputField nmc_fields_setting_wireless_security[];
extern NmcOutputField nmc_fields_setting_ip4_config[];
extern NmcOutputField nmc_fields_setting_ip6_config[];
extern NmcOutputField nmc_fields_setting_serial[];
extern NmcOutputField nmc_fields_setting_ppp[];
extern NmcOutputField nmc_fields_setting_pppoe[];
extern NmcOutputField nmc_fields_setting_adsl[];
extern NmcOutputField nmc_fields_setting_gsm[];
extern NmcOutputField nmc_fields_setting_cdma[];
extern NmcOutputField nmc_fields_setting_bluetooth[];
extern NmcOutputField nmc_fields_setting_olpc_mesh[];
extern NmcOutputField nmc_fields_setting_vpn[];
extern NmcOutputField nmc_fields_setting_wimax[];
extern NmcOutputField nmc_fields_setting_infiniband[];
extern NmcOutputField nmc_fields_setting_bond[];
extern NmcOutputField nmc_fields_setting_vlan[];
extern NmcOutputField nmc_fields_setting_bridge[];
extern NmcOutputField nmc_fields_setting_bridge_port[];
extern NmcOutputField nmc_fields_setting_team[];
extern NmcOutputField nmc_fields_setting_team_port[];
extern NmcOutputField nmc_fields_setting_dcb[];
extern NmcOutputField nmc_fields_setting_tun[];
extern NmcOutputField nmc_fields_setting_ip_tunnel[];
extern NmcOutputField nmc_fields_setting_macvlan[];
extern NmcOutputField nmc_fields_setting_macsec[];
extern NmcOutputField nmc_fields_setting_vxlan[];
extern NmcOutputField nmc_fields_setting_proxy[];
extern NmcOutputField nmc_fields_setting_dummy[];
#endif /* NMC_SETTINGS_H */

View file

@ -27,17 +27,11 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include "nm-client-utils.h"
#include "utils.h"
#include "common.h"
gboolean
matches (const char *cmd, const char *pattern)
{
size_t len = strlen (cmd);
if (!len || len > strlen (pattern))
return FALSE;
return memcmp (pattern, cmd, len) == 0;
}
#include "settings.h"
static gboolean
parse_global_arg (NmCli *nmc, const char *arg)
@ -319,24 +313,26 @@ nmc_term_format_sequence (NmcTermFormat format)
}
static gboolean
use_colors (NmCli *nmc)
use_colors (NmcColorOption color_option)
{
if (nmc == NULL)
return FALSE;
if (color_option == NMC_USE_COLOR_AUTO) {
static NmcColorOption cached = NMC_USE_COLOR_AUTO;
if (nmc->use_colors == NMC_USE_COLOR_AUTO) {
if ( g_strcmp0 (g_getenv ("TERM"), "dumb") == 0
|| !isatty (fileno (stdout)))
nmc->use_colors = NMC_USE_COLOR_NO;
else
nmc->use_colors = NMC_USE_COLOR_YES;
if (G_UNLIKELY (cached == NMC_USE_COLOR_AUTO)) {
if ( g_strcmp0 (g_getenv ("TERM"), "dumb") == 0
|| !isatty (fileno (stdout)))
cached = NMC_USE_COLOR_NO;
else
cached = NMC_USE_COLOR_YES;
}
return cached == NMC_USE_COLOR_YES;
}
return nmc->use_colors == NMC_USE_COLOR_YES;
return color_option == NMC_USE_COLOR_YES;
}
char *
nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
nmc_colorize (NmcColorOption color_option, NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
{
va_list args;
char *str, *colored;
@ -347,7 +343,7 @@ nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char *
str = g_strdup_vprintf (fmt, args);
va_end (args);
if (!use_colors (nmc))
if (!use_colors (color_option))
return str;
ansi_color = nmc_term_color_sequence (color);
@ -425,137 +421,6 @@ nmc_filter_out_colors (const char *str)
return filtered;
}
/*
* Convert string to signed integer.
* If required, the resulting number is checked to be in the <min,max> range.
*/
gboolean
nmc_string_to_int_base (const char *str,
int base,
gboolean range_check,
long int min,
long int max,
long int *value)
{
char *end;
long int tmp;
errno = 0;
tmp = strtol (str, &end, base);
if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
return FALSE;
}
*value = tmp;
return TRUE;
}
/*
* Convert string to unsigned integer.
* If required, the resulting number is checked to be in the <min,max> range.
*/
gboolean
nmc_string_to_uint_base (const char *str,
int base,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value)
{
char *end;
unsigned long int tmp;
errno = 0;
tmp = strtoul (str, &end, base);
if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
return FALSE;
}
*value = tmp;
return TRUE;
}
gboolean
nmc_string_to_int (const char *str,
gboolean range_check,
long int min,
long int max,
long int *value)
{
return nmc_string_to_int_base (str, 10, range_check, min, max, value);
}
gboolean
nmc_string_to_uint (const char *str,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value)
{
return nmc_string_to_uint_base (str, 10, range_check, min, max, value);
}
gboolean
nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
{
const char *s_true[] = { "true", "yes", "on", NULL };
const char *s_false[] = { "false", "no", "off", NULL };
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (g_strcmp0 (str, "o") == 0) {
g_set_error (error, 1, 0,
/* Translators: the first %s is the partial value entered by
* the user, the second %s a list of compatible values.
*/
_("'%s' is ambiguous (%s)"), str, "on x off");
return FALSE;
}
if (nmc_string_is_valid (str, s_true, NULL))
*val_bool = TRUE;
else if (nmc_string_is_valid (str, s_false, NULL))
*val_bool = FALSE;
else {
g_set_error (error, 1, 0,
_("'%s' is not valid; use [%s] or [%s]"),
str, "true, yes, on", "false, no, off");
return FALSE;
}
return TRUE;
}
gboolean
nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error)
{
const char *s_true[] = { "true", "yes", "on", NULL };
const char *s_false[] = { "false", "no", "off", NULL };
const char *s_unknown[] = { "unknown", NULL };
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (g_strcmp0 (str, "o") == 0) {
g_set_error (error, 1, 0,
/* Translators: the first %s is the partial value entered by
* the user, the second %s a list of compatible values.
*/
_("'%s' is ambiguous (%s)"), str, "on x off");
return FALSE;
}
if (nmc_string_is_valid (str, s_true, NULL))
*val = NMC_TRI_STATE_YES;
else if (nmc_string_is_valid (str, s_false, NULL))
*val = NMC_TRI_STATE_NO;
else if (nmc_string_is_valid (str, s_unknown, NULL))
*val = NMC_TRI_STATE_UNKNOWN;
else {
g_set_error (error, 1, 0,
_("'%s' is not valid; use [%s], [%s] or [%s]"),
str, "true, yes, on", "false, no, off", "unknown");
return FALSE;
}
return TRUE;
}
/*
* Ask user for input and return the string.
* The caller is responsible for freeing the returned string.
@ -618,57 +483,6 @@ nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
return 0;
}
/*
* Check whether 'input' is contained in 'allowed' array. It performs case
* insensitive comparison and supports shortcut strings if they are unique.
* Returns: a pointer to found string in allowed array on success or NULL.
* On failure: error->code : 0 - string not found; 1 - string is ambiguous
*/
const char *
nmc_string_is_valid (const char *input, const char **allowed, GError **error)
{
const char **p;
size_t input_ln, p_len;
gboolean prev_match = FALSE;
const char *ret = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (!input || !*input)
goto finish;
input_ln = strlen (input);
for (p = allowed; p && *p; p++) {
p_len = strlen (*p);
if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
if (input_ln == p_len) {
ret = *p;
break;
}
if (!prev_match)
ret = *p;
else {
g_set_error (error, 1, 1, _("'%s' is ambiguous (%s x %s)"),
input, ret, *p);
return NULL;
}
prev_match = TRUE;
}
}
finish:
if (ret == NULL) {
char *valid_vals = g_strjoinv (", ", (char **) allowed);
if (!input || !*input)
g_set_error (error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
else
g_set_error (error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
g_free (valid_vals);
}
return ret;
}
/*
* Convert string array (char **) to description string in the form of:
* "[string1, string2, ]"
@ -676,7 +490,7 @@ finish:
* Returns: a newly allocated string. Caller must free it with g_free().
*/
char *
nmc_util_strv_for_display (const char **strv, gboolean brackets)
nmc_util_strv_for_display (const char *const*strv, gboolean brackets)
{
GString *result;
guint i = 0;
@ -696,31 +510,6 @@ nmc_util_strv_for_display (const char **strv, gboolean brackets)
return g_string_free (result, FALSE);
}
/*
* Wrapper function for g_strsplit_set() that removes empty strings
* from the vector as they are not useful in most cases.
*/
char **
nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens)
{
char **result;
uint i;
uint j;
result = g_strsplit_set (str, delimiter, max_tokens);
/* remove empty strings */
for (i = 0; result && result[i]; i++) {
if (*(result[i]) == '\0') {
g_free (result[i]);
for (j = i; result[j]; j++)
result[j] = result[j + 1];
i--;
}
}
return result;
}
/*
* Find out how many columns an UTF-8 string occupies on the screen.
*/
@ -869,16 +658,27 @@ parse_output_fields (const char *fields_str,
for (i = 0; fields_array[i].name; i++) {
if (strcasecmp (left, fields_array[i].name) == 0) {
NmcOutputField *valid_names = fields_array[i].group;
const NmcOutputField *valid_names = fields_array[i].group_list;
const NMMetaSettingInfoEditor *setting_info = fields_array[i].setting_info;
idx = i;
if (!right && !valid_names) {
if (!right && !valid_names && !setting_info) {
found = TRUE;
break;
}
for (j = 0; valid_names && valid_names[j].name; j++) {
if (!right || strcasecmp (right, valid_names[j].name) == 0) {
found = TRUE;
break;
if (valid_names) {
for (j = 0; valid_names[j].name; j++) {
if (!right || strcasecmp (right, valid_names[j].name) == 0) {
found = TRUE;
break;
}
}
} else if (setting_info) {
for (j = 1; j < setting_info->properties_num; j++) {
if (!right || strcasecmp (right, setting_info->properties[j].property_name) == 0) {
found = TRUE;
break;
}
}
}
if (found)
@ -946,11 +746,20 @@ nmc_get_allowed_fields (const NmcOutputField fields_array[], int group_idx)
GString *allowed_fields = g_string_sized_new (256);
int i;
if (group_idx != -1 && fields_array[group_idx].group) {
NmcOutputField *second_level = fields_array[group_idx].group;
for (i = 0; second_level[i].name; i++)
if (group_idx != -1 && fields_array[group_idx].group_list) {
const NmcOutputField *second_level = fields_array[group_idx].group_list;
for (i = 0; second_level[i].name; i++) {
g_string_append_printf (allowed_fields, "%s.%s,",
fields_array[group_idx].name, second_level[i].name);
}
} else if (group_idx != -1 && fields_array[group_idx].setting_info) {
const NMMetaSettingInfoEditor *second_level = fields_array[group_idx].setting_info;
for (i = 1; i < second_level->properties_num; i++) {
g_string_append_printf (allowed_fields, "%s.%s,",
fields_array[group_idx].name, second_level->properties[i].property_name);
}
} else {
for (i = 0; fields_array[i].name; i++)
g_string_append_printf (allowed_fields, "%s,", fields_array[i].name);
@ -973,28 +782,28 @@ nmc_dup_fields_array (NmcOutputField fields[], size_t size, guint32 flags)
}
void
nmc_empty_output_fields (NmCli *nmc)
nmc_empty_output_fields (NmcOutputData *output_data)
{
guint i;
/* Free values in field structure */
for (i = 0; i < nmc->output_data->len; i++) {
NmcOutputField *fld_arr = g_ptr_array_index (nmc->output_data, i);
for (i = 0; i < output_data->output_data->len; i++) {
NmcOutputField *fld_arr = g_ptr_array_index (output_data->output_data, i);
nmc_free_output_field_values (fld_arr);
}
/* Empty output_data array */
if (nmc->output_data->len > 0)
g_ptr_array_remove_range (nmc->output_data, 0, nmc->output_data->len);
if (output_data->output_data->len > 0)
g_ptr_array_remove_range (output_data->output_data, 0, output_data->output_data->len);
if (nmc->print_fields.indices) {
g_array_free (nmc->print_fields.indices, TRUE);
nmc->print_fields.indices = NULL;
if (output_data->print_fields.indices) {
g_array_free (output_data->print_fields.indices, TRUE);
output_data->print_fields.indices = NULL;
}
}
static const char *
colorize_string (NmCli *nmc,
colorize_string (NmcColorOption color_option,
NmcTermColor color,
NmcTermFormat color_fmt,
const char *str,
@ -1002,9 +811,9 @@ colorize_string (NmCli *nmc,
{
const char *out = str;
if ( use_colors (nmc)
if ( use_colors (color_option)
&& (color != NMC_TERM_COLOR_NORMAL || color_fmt != NMC_TERM_FORMAT_NORMAL)) {
*out_to_free = nmc_colorize (nmc, color, color_fmt, "%s", str);
*out_to_free = nmc_colorize (color_option, color, color_fmt, "%s", str);
out = *out_to_free;
}
@ -1012,36 +821,38 @@ colorize_string (NmCli *nmc,
}
static const char *
get_value_to_print (NmCli *nmc,
NmcOutputField *field,
get_value_to_print (NmcColorOption color_option,
const NmcOutputField *field,
gboolean field_name,
const char *not_set_str,
char **out_to_free)
{
gboolean is_array = field->value_is_array;
char *value;
const char *value;
const char *out;
gboolean free_value;
gs_free char *free_value = NULL;
nm_assert (out_to_free && !*out_to_free);
if (field_name)
value = _(field->name_l10n);
else
value = _(field->name);
else {
value = field->value
? (is_array
? g_strjoinv (" | ", (char **) field->value)
: (*((char *) field->value)
? (char *) field->value
: (char *) not_set_str))
: (char *) not_set_str;
free_value = field->value && is_array && !field_name;
? (free_value = g_strjoinv (" | ", (char **) field->value))
: (*((const char *) field->value))
? field->value
: not_set_str)
: not_set_str;
}
/* colorize the value */
out = colorize_string (nmc, field->color, field->color_fmt, value, out_to_free);
if (*out_to_free) {
if (free_value)
g_free (value);
} else if (free_value)
*out_to_free = value;
out = colorize_string (color_option, field->color, field->color_fmt, value, out_to_free);
if (out && out == free_value) {
nm_assert (!*out_to_free);
*out_to_free = g_steal_pointer (&free_value);
}
return out;
}
@ -1054,7 +865,7 @@ get_value_to_print (NmCli *nmc,
* of 'field_values' array.
*/
void
print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
print_required_fields (const NmcConfig *nmc_config, const NmcPrintFields *print_fields, const NmcOutputField *field_values)
{
GString *str;
int width1, width2;
@ -1063,11 +874,10 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
char *indent_str;
const char *not_set_str = "--";
int i;
const NmcPrintFields fields = nmc->print_fields;
gboolean multiline = nmc->multiline_output;
gboolean terse = (nmc->print_output == NMC_PRINT_TERSE);
gboolean pretty = (nmc->print_output == NMC_PRINT_PRETTY);
gboolean escape = nmc->escape_values;
gboolean multiline = nmc_config->multiline_output;
gboolean terse = (nmc_config->print_output == NMC_PRINT_TERSE);
gboolean pretty = (nmc_config->print_output == NMC_PRINT_PRETTY);
gboolean escape = nmc_config->escape_values;
gboolean main_header_add = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ADD;
gboolean main_header_only = field_values[0].flags & NMC_OF_FLAG_MAIN_HEADER_ONLY;
gboolean field_names = field_values[0].flags & NMC_OF_FLAG_FIELD_NAMES;
@ -1080,7 +890,7 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
/* --- Main header --- */
if (main_header && pretty) {
int header_width = nmc_string_screen_width (fields.header_name, NULL) + 4;
int header_width = nmc_string_screen_width (print_fields->header_name, NULL) + 4;
if (multiline) {
table_width = header_width < ML_HEADER_WIDTH ? ML_HEADER_WIDTH : header_width;
@ -1090,10 +900,10 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
line = g_strnfill (table_width, '=');
}
width1 = strlen (fields.header_name);
width2 = nmc_string_screen_width (fields.header_name, NULL);
width1 = strlen (print_fields->header_name);
width2 = nmc_string_screen_width (print_fields->header_name, NULL);
g_print ("%s\n", line);
g_print ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name);
g_print ("%*s\n", (table_width + width2)/2 + width1 - width2, print_fields->header_name);
g_print ("%s\n", line);
g_free (line);
}
@ -1110,9 +920,9 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
if (multiline) {
for (i = 0; i < fields.indices->len; i++) {
for (i = 0; i < print_fields->indices->len; i++) {
char *tmp;
int idx = g_array_index (fields.indices, int, i);
int idx = g_array_index (print_fields->indices, int, i);
gboolean is_array = field_values[idx].value_is_array;
/* section prefix can't be an array */
@ -1129,12 +939,12 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
for (p = (const char **) field_values[idx].value, j = 1; p && *p; p++, j++) {
val = *p ? *p : not_set_str;
print_val = colorize_string (nmc, field_values[idx].color, field_values[idx].color_fmt,
print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt,
val, &val_to_free);
tmp = g_strdup_printf ("%s%s%s[%d]:",
section_prefix ? (const char*) field_values[0].value : "",
section_prefix ? "." : "",
_(field_values[idx].name_l10n),
_(field_values[idx].name),
j);
width1 = strlen (tmp);
width2 = nmc_string_screen_width (tmp, NULL);
@ -1149,12 +959,12 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
gs_free char *val_to_free = NULL;
val = val && *val ? val : not_set_str;
print_val = colorize_string (nmc, field_values[idx].color, field_values[idx].color_fmt,
print_val = colorize_string (nmc_config->use_colors, field_values[idx].color, field_values[idx].color_fmt,
val, &val_to_free);
tmp = g_strdup_printf ("%s%s%s:",
section_prefix ? hdr_name : "",
section_prefix ? "." : "",
_(field_values[idx].name_l10n));
_(field_values[idx].name));
width1 = strlen (tmp);
width2 = nmc_string_screen_width (tmp, NULL);
g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, print_val);
@ -1174,10 +984,10 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
str = g_string_new (NULL);
for (i = 0; i < fields.indices->len; i++) {
int idx = g_array_index (fields.indices, int, i);
for (i = 0; i < print_fields->indices->len; i++) {
int idx = g_array_index (print_fields->indices, int, i);
gs_free char *val_to_free = NULL;
const char *value = get_value_to_print (nmc, (NmcOutputField *) field_values+idx, field_names,
const char *value = get_value_to_print (nmc_config->use_colors, (NmcOutputField *) field_values+idx, field_names,
not_set_str, &val_to_free);
if (terse) {
@ -1205,8 +1015,8 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
/* Print actual values */
if (str->len > 0) {
g_string_truncate (str, str->len-1); /* Chop off last column separator */
if (fields.indent > 0) {
indent_str = g_strnfill (fields.indent, ' ');
if (print_fields->indent > 0) {
indent_str = g_strnfill (print_fields->indent, ' ');
g_string_prepend (str, indent_str);
g_free (indent_str);
}
@ -1223,27 +1033,19 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
g_string_free (str, TRUE);
}
/*
* Print nmc->output_data
*
* It first finds out maximal string length in columns and fill the value to
* 'width' member of NmcOutputField, so that columns in tabular output are
* properly aligned. Then each object (row in tabular) is printed using
* print_required_fields() function.
*/
void
print_data (NmCli *nmc)
print_data_prepare_width (GPtrArray *output_data)
{
int i, j;
size_t len;
NmcOutputField *row;
int num_fields = 0;
if (!nmc->output_data || nmc->output_data->len < 1)
if (!output_data || output_data->len < 1)
return;
/* How many fields? */
row = g_ptr_array_index (nmc->output_data, 0);
row = g_ptr_array_index (output_data, 0);
while (row->name) {
num_fields++;
row++;
@ -1252,27 +1054,32 @@ print_data (NmCli *nmc)
/* Find out maximal string lengths */
for (i = 0; i < num_fields; i++) {
size_t max_width = 0;
for (j = 0; j < nmc->output_data->len; j++) {
for (j = 0; j < output_data->len; j++) {
gboolean field_names;
gs_free char * val_to_free = NULL;
const char *value;
row = g_ptr_array_index (nmc->output_data, j);
row = g_ptr_array_index (output_data, j);
field_names = row[0].flags & NMC_OF_FLAG_FIELD_NAMES;
value = get_value_to_print (NULL, row+i, field_names, "--", &val_to_free);
value = get_value_to_print (NMC_USE_COLOR_NO, row+i, field_names, "--", &val_to_free);
len = nmc_string_screen_width (value, NULL);
max_width = len > max_width ? len : max_width;
}
for (j = 0; j < nmc->output_data->len; j++) {
row = g_ptr_array_index (nmc->output_data, j);
for (j = 0; j < output_data->len; j++) {
row = g_ptr_array_index (output_data, j);
row[i].width = max_width + 1;
}
}
}
/* Now we can print the data. */
for (i = 0; i < nmc->output_data->len; i++) {
row = g_ptr_array_index (nmc->output_data, i);
print_required_fields (nmc, row);
void
print_data (const NmcConfig *nmc_config, const NmcOutputData *out)
{
guint i;
for (i = 0; i < out->output_data->len; i++) {
print_required_fields (nmc_config, &out->print_fields,
g_ptr_array_index (out->output_data, i));
}
}

View file

@ -32,56 +32,25 @@ typedef struct {
gboolean found;
} nmc_arg_t;
typedef enum {
NMC_TRI_STATE_NO,
NMC_TRI_STATE_YES,
NMC_TRI_STATE_UNKNOWN,
} NMCTriStateValue;
/* === Functions === */
gboolean matches (const char *cmd, const char *pattern);
int next_arg (NmCli *nmc, int *argc, char ***argv);
gboolean nmc_arg_is_help (const char *arg);
gboolean nmc_arg_is_option (const char *arg, const char *opt_name);
gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***argv, GError **error);
char *ssid_to_hex (const char *str, gsize len);
gboolean nmc_string_to_int_base (const char *str,
int base,
gboolean range_check,
long int min,
long int max,
long int *value);
gboolean nmc_string_to_uint_base (const char *str,
int base,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value);
gboolean nmc_string_to_int (const char *str,
gboolean range_check,
long int min,
long int max,
long int *value);
gboolean nmc_string_to_uint (const char *str,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value);
gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
void nmc_terminal_erase_line (void);
void nmc_terminal_show_progress (const char *str);
const char *nmc_term_color_sequence (NmcTermColor color);
const char *nmc_term_format_sequence (NmcTermFormat format);
NmcTermColor nmc_term_color_parse_string (const char *str, GError **error);
char *nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char * fmt, ...) _nm_printf (4, 5);
char *nmc_colorize (NmcColorOption color_option, NmcTermColor color, NmcTermFormat format, const char * fmt, ...) _nm_printf (4, 5);
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);
int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote,
char ***argv, int *argc);
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
char * nmc_util_strv_for_display (const char **strv, gboolean brackets);
char * nmc_util_strv_for_display (const char *const*strv, gboolean brackets);
char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
int nmc_string_screen_width (const char *start, const char *end);
void set_val_str (NmcOutputField fields_array[], guint32 index, char *value);
@ -98,8 +67,9 @@ GArray *parse_output_fields (const char *fields_str,
GError **error);
char *nmc_get_allowed_fields (const NmcOutputField fields_array[], int group_idx);
NmcOutputField *nmc_dup_fields_array (NmcOutputField fields[], size_t size, guint32 flags);
void nmc_empty_output_fields (NmCli *nmc);
void print_required_fields (NmCli *nmc, const NmcOutputField field_values[]);
void print_data (NmCli *nmc);
void nmc_empty_output_fields (NmcOutputData *output_data);
void print_required_fields (const NmcConfig *nmc_config, const NmcPrintFields *print_fields, const NmcOutputField field_values[]);
void print_data_prepare_width (GPtrArray *output_data);
void print_data (const NmcConfig *nmc_config, const NmcOutputData *out);
#endif /* NMC_UTILS_H */

View file

@ -0,0 +1,239 @@
/* nmcli - command-line tool to control NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* 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.
*/
#include "nm-default.h"
#include "nm-client-utils.h"
/*
* Convert string to signed integer.
* If required, the resulting number is checked to be in the <min,max> range.
*/
gboolean
nmc_string_to_int_base (const char *str,
int base,
gboolean range_check,
long int min,
long int max,
long int *value)
{
char *end;
long int tmp;
errno = 0;
tmp = strtol (str, &end, base);
if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
return FALSE;
}
*value = tmp;
return TRUE;
}
/*
* Convert string to unsigned integer.
* If required, the resulting number is checked to be in the <min,max> range.
*/
gboolean
nmc_string_to_uint_base (const char *str,
int base,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value)
{
char *end;
unsigned long int tmp;
errno = 0;
tmp = strtoul (str, &end, base);
if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) {
return FALSE;
}
*value = tmp;
return TRUE;
}
gboolean
nmc_string_to_int (const char *str,
gboolean range_check,
long int min,
long int max,
long int *value)
{
return nmc_string_to_int_base (str, 10, range_check, min, max, value);
}
gboolean
nmc_string_to_uint (const char *str,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value)
{
return nmc_string_to_uint_base (str, 10, range_check, min, max, value);
}
gboolean
nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error)
{
const char *s_true[] = { "true", "yes", "on", NULL };
const char *s_false[] = { "false", "no", "off", NULL };
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (g_strcmp0 (str, "o") == 0) {
g_set_error (error, 1, 0,
/* Translators: the first %s is the partial value entered by
* the user, the second %s a list of compatible values.
*/
_("'%s' is ambiguous (%s)"), str, "on x off");
return FALSE;
}
if (nmc_string_is_valid (str, s_true, NULL))
*val_bool = TRUE;
else if (nmc_string_is_valid (str, s_false, NULL))
*val_bool = FALSE;
else {
g_set_error (error, 1, 0,
_("'%s' is not valid; use [%s] or [%s]"),
str, "true, yes, on", "false, no, off");
return FALSE;
}
return TRUE;
}
gboolean
nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error)
{
const char *s_true[] = { "true", "yes", "on", NULL };
const char *s_false[] = { "false", "no", "off", NULL };
const char *s_unknown[] = { "unknown", NULL };
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (g_strcmp0 (str, "o") == 0) {
g_set_error (error, 1, 0,
/* Translators: the first %s is the partial value entered by
* the user, the second %s a list of compatible values.
*/
_("'%s' is ambiguous (%s)"), str, "on x off");
return FALSE;
}
if (nmc_string_is_valid (str, s_true, NULL))
*val = NMC_TRI_STATE_YES;
else if (nmc_string_is_valid (str, s_false, NULL))
*val = NMC_TRI_STATE_NO;
else if (nmc_string_is_valid (str, s_unknown, NULL))
*val = NMC_TRI_STATE_UNKNOWN;
else {
g_set_error (error, 1, 0,
_("'%s' is not valid; use [%s], [%s] or [%s]"),
str, "true, yes, on", "false, no, off", "unknown");
return FALSE;
}
return TRUE;
}
/*
* Check whether 'input' is contained in 'allowed' array. It performs case
* insensitive comparison and supports shortcut strings if they are unique.
* Returns: a pointer to found string in allowed array on success or NULL.
* On failure: error->code : 0 - string not found; 1 - string is ambiguous
*/
const char *
nmc_string_is_valid (const char *input, const char **allowed, GError **error)
{
const char **p;
size_t input_ln, p_len;
gboolean prev_match = FALSE;
const char *ret = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
if (!input || !*input)
goto finish;
input_ln = strlen (input);
for (p = allowed; p && *p; p++) {
p_len = strlen (*p);
if (g_ascii_strncasecmp (input, *p, input_ln) == 0) {
if (input_ln == p_len) {
ret = *p;
break;
}
if (!prev_match)
ret = *p;
else {
g_set_error (error, 1, 1, _("'%s' is ambiguous (%s x %s)"),
input, ret, *p);
return NULL;
}
prev_match = TRUE;
}
}
finish:
if (ret == NULL) {
char *valid_vals = g_strjoinv (", ", (char **) allowed);
if (!input || !*input)
g_set_error (error, 1, 0, _("missing name, try one of [%s]"), valid_vals);
else
g_set_error (error, 1, 0, _("'%s' not among [%s]"), input, valid_vals);
g_free (valid_vals);
}
return ret;
}
/*
* Wrapper function for g_strsplit_set() that removes empty strings
* from the vector as they are not useful in most cases.
*/
char **
nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens)
{
char **result;
uint i;
uint j;
result = g_strsplit_set (str, delimiter, max_tokens);
/* remove empty strings */
for (i = 0; result && result[i]; i++) {
if (*(result[i]) == '\0') {
g_free (result[i]);
for (j = i; result[j]; j++)
result[j] = result[j + 1];
i--;
}
}
return result;
}
gboolean
matches (const char *cmd, const char *pattern)
{
size_t len = strlen (cmd);
if (!len || len > strlen (pattern))
return FALSE;
return memcmp (pattern, cmd, len) == 0;
}

View file

@ -0,0 +1,63 @@
/* nmcli - command-line tool to control NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* 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.
*/
#ifndef __NM_CLIENT_UTILS_H__
#define __NM_CLIENT_UTILS_H__
#include "nm-meta-setting.h"
typedef enum {
NMC_TRI_STATE_NO,
NMC_TRI_STATE_YES,
NMC_TRI_STATE_UNKNOWN,
} NMCTriStateValue;
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens);
gboolean nmc_string_to_int_base (const char *str,
int base,
gboolean range_check,
long int min,
long int max,
long int *value);
gboolean nmc_string_to_uint_base (const char *str,
int base,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value);
gboolean nmc_string_to_int (const char *str,
gboolean range_check,
long int min,
long int max,
long int *value);
gboolean nmc_string_to_uint (const char *str,
gboolean range_check,
unsigned long int min,
unsigned long int max,
unsigned long int *value);
gboolean nmc_string_to_bool (const char *str, gboolean *val_bool, GError **error);
gboolean nmc_string_to_tristate (const char *str, NMCTriStateValue *val, GError **error);
gboolean matches (const char *cmd, const char *pattern);
#endif /* __NM_CLIENT_UTILS_H__ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
/* nmcli - command-line tool to control NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* 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.
*/
#ifndef __NM_META_SETTING_DESC_H__
#define __NM_META_SETTING_DESC_H__
#include "nm-meta-setting.h"
#define NM_META_TEXT_HIDDEN "<hidden>"
typedef enum {
NM_META_ACCESSOR_GET_TYPE_PRETTY,
NM_META_ACCESSOR_GET_TYPE_PARSABLE,
} NMMetaAccessorGetType;
typedef enum {
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC = (1LL << 0),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX = (1LL << 1),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT = (1LL << 2),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N = (1LL << 3),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC = (1LL << 4),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX = (1LL << 5),
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT = (1LL << 6),
} NMMetaPropertyTypFlags;
typedef enum {
NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT,
NM_META_PROPERTY_TYPE_MAC_MODE_CLONED,
NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND,
} NMMetaPropertyTypeMacMode;
typedef struct _NMMetaSettingInfoEditor NMMetaSettingInfoEditor;
typedef struct _NMMetaPropertyInfo NMMetaPropertyInfo;
typedef struct _NMMetaPropertyType NMMetaPropertyType;
typedef struct _NMMetaPropertyTypData NMMetaPropertyTypData;
struct _NMMetaPropertyType {
const char *(*describe_fcn) (const NMMetaSettingInfoEditor *setting_info,
const NMMetaPropertyInfo *property_info,
char **out_to_free);
char *(*get_fcn) (const NMMetaSettingInfoEditor *setting_info,
const NMMetaPropertyInfo *property_info,
NMSetting *setting,
NMMetaAccessorGetType get_type,
gboolean show_secrets);
gboolean (*set_fcn) (const NMMetaSettingInfoEditor *setting_info,
const NMMetaPropertyInfo *property_info,
NMSetting *setting,
const char *value,
GError **error);
gboolean (*remove_fcn) (const NMMetaSettingInfoEditor *setting_info,
const NMMetaPropertyInfo *property_info,
NMSetting *setting,
const char *option,
guint32 idx,
GError **error);
const char *const*(*values_fcn) (const NMMetaSettingInfoEditor *setting_info,
const NMMetaPropertyInfo *property_info,
char ***out_to_free);
};
struct _NMUtilsEnumValueInfo;
struct _NMMetaPropertyTypData {
union {
struct {
gboolean (*fcn) (NMSetting *setting);
} get_with_default;
struct {
GType (*get_gtype) (void);
int min;
int max;
const struct _NMUtilsEnumValueInfo *value_infos;
} gobject_enum;
struct {
guint32 (*get_fcn) (NMSetting *setting);
} mtu;
struct {
NMMetaPropertyTypeMacMode mode;
} mac;
} subtype;
const char *const*values_static;
NMMetaPropertyTypFlags typ_flags;
};
struct _NMMetaPropertyInfo {
const char *property_name;
/* the property list for now must contain as first field the
* "name", which isn't a regular property. This is required by
* NmcOutputField and this first field is ignored for the
* group_list/setting_info. */
bool is_name:1;
bool is_secret:1;
const char *describe_message;
const NMMetaPropertyType *property_type;
const NMMetaPropertyTypData *property_typ_data;
};
struct _NMMetaSettingInfoEditor {
const NMMetaSettingInfo *general;
/* the order of the properties matter. The first *must* be the
* "name", and then the order is as they are listed by default. */
const NMMetaPropertyInfo *properties;
guint properties_num;
};
extern const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[_NM_META_SETTING_TYPE_NUM];
/* FIXME: don't expose this function on it's own, at least not from this file. */
const char *nmc_bond_validate_mode (const char *mode, GError **error);
#endif /* __NM_META_SETTING_DESC_H__ */

View file

@ -204,8 +204,6 @@ gboolean _nm_utils_check_module_file (const char *name,
gpointer user_data,
GError **error);
char *_nm_utils_enum_to_str_full (GType type, int value, const char *sep);
#define NM_UTILS_UUID_TYPE_LEGACY 0
#define NM_UTILS_UUID_TYPE_VARIANT3 1

View file

@ -28,7 +28,7 @@
#include "nm-setting-8021x.h"
#include "nm-core-internal.h"
#include "nm-setting-metadata.h"
#include "nm-meta-setting.h"
/*****************************************************************************/

View file

@ -224,7 +224,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("property is invalid"));
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE);
return FALSE;
}

View file

@ -438,7 +438,7 @@ set_property (GObject *object, guint prop_id,
nm_clear_g_free (&priv->keys);
return;
}
g_hash_table_iter_init (&iter, priv->data);
g_hash_table_iter_init (&iter, data);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) {
if (!nm_setting_user_check_key (key, NULL))
g_return_if_reached ();

View file

@ -37,6 +37,7 @@
#include <jansson.h>
#endif
#include "nm-utils/nm-enum-utils.h"
#include "nm-common-macros.h"
#include "nm-utils-private.h"
#include "nm-setting-private.h"
@ -4249,263 +4250,6 @@ int _nm_utils_dns_option_find_idx (GPtrArray *array, const char *option)
return -1;
}
#define IS_FLAGS_SEPARATOR(ch) (NM_IN_SET ((ch), ' ', '\t', ',', '\n', '\r'))
static gboolean
_is_hex_string (const char *str)
{
return str[0] == '0'
&& str[1] == 'x'
&& str[2]
&& NM_STRCHAR_ALL (&str[2], ch, g_ascii_isxdigit (ch));
}
static gboolean
_enum_is_valid_enum_nick (const char *str)
{
return str[0]
&& !NM_STRCHAR_ANY (str, ch, g_ascii_isspace (ch))
&& !NM_STRCHAR_ALL (str, ch, g_ascii_isdigit (ch));
}
static gboolean
_enum_is_valid_flags_nick (const char *str)
{
return str[0]
&& !NM_STRCHAR_ANY (str, ch, IS_FLAGS_SEPARATOR (ch))
&& !_is_hex_string (str);
}
char *
_nm_utils_enum_to_str_full (GType type,
int value,
const char *flags_separator)
{
GTypeClass *class;
char *ret;
if ( flags_separator
&& ( !flags_separator[0]
|| NM_STRCHAR_ANY (flags_separator, ch, !IS_FLAGS_SEPARATOR (ch))))
g_return_val_if_reached (NULL);
class = g_type_class_ref (type);
if (G_IS_ENUM_CLASS (class)) {
GEnumValue *enum_value;
enum_value = g_enum_get_value (G_ENUM_CLASS (class), value);
if ( !enum_value
|| !_enum_is_valid_enum_nick (enum_value->value_nick))
ret = g_strdup_printf ("%d", value);
else
ret = strdup (enum_value->value_nick);
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsValue *flags_value;
GString *str = g_string_new ("");
flags_separator = flags_separator ?: " ";
while (value) {
flags_value = g_flags_get_first_value (G_FLAGS_CLASS (class), value);
if (str->len)
g_string_append (str, flags_separator);
if ( !flags_value
|| !_enum_is_valid_flags_nick (flags_value->value_nick)) {
g_string_append_printf (str, "0x%x", (unsigned) value);
break;
}
g_string_append (str, flags_value->value_nick);
value &= ~flags_value->value;
}
ret = g_string_free (str, FALSE);
} else
g_return_val_if_reached (NULL);
g_type_class_unref (class);
return ret;
}
/**
* nm_utils_enum_to_str:
* @type: the %GType of the enum
* @value: the value to be translated
*
* Converts an enum value to its string representation. If the enum is a
* %G_TYPE_FLAGS the function returns a comma-separated list of matching values.
* If the enum is a %G_TYPE_ENUM and the given value is not valid the
* function returns %NULL.
*
* Returns: a newly allocated string or %NULL
*
* Since: 1.2
*/
char *
nm_utils_enum_to_str (GType type, int value)
{
return _nm_utils_enum_to_str_full (type, value, ", ");
}
/**
* nm_utils_enum_from_str:
* @type: the %GType of the enum
* @str: the input string
* @out_value: (out) (allow-none): the output value
* @err_token: (out) (allow-none) (transfer full): location to store the first unrecognized token
*
* Converts a string to the matching enum value.
*
* If the enum is a %G_TYPE_FLAGS the function returns the logical OR of values
* matching the comma-separated tokens in the string; if an unknown token is found
* the function returns %FALSE and stores a pointer to a newly allocated string
* containing the unrecognized token in @err_token.
*
* Returns: %TRUE if the conversion was successful, %FALSE otherwise
*
* Since: 1.2
*/
gboolean
nm_utils_enum_from_str (GType type, const char *str,
int *out_value, char **err_token)
{
GTypeClass *class;
gboolean ret = FALSE;
int value = 0;
gs_free char *str_clone = NULL;
char *s;
gint64 v64;
g_return_val_if_fail (str, FALSE);
str_clone = strdup (str);
s = nm_str_skip_leading_spaces (str_clone);
g_strchomp (s);
class = g_type_class_ref (type);
if (G_IS_ENUM_CLASS (class)) {
GEnumValue *enum_value;
if (s[0]) {
if (NM_STRCHAR_ALL (s, ch, g_ascii_isdigit (ch))) {
v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXINT, -1);
if (v64 != -1) {
value = (int) v64;
ret = TRUE;
}
} else {
enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (class), s);
if (enum_value) {
value = enum_value->value;
ret = TRUE;
}
}
}
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsValue *flags_value;
ret = TRUE;
while (s[0]) {
char *s_end;
for (s_end = s; s_end[0]; s_end++) {
if (IS_FLAGS_SEPARATOR (s_end[0])) {
s_end[0] = '\0';
s_end++;
break;
}
}
if (s[0]) {
if (_is_hex_string (s)) {
v64 = _nm_utils_ascii_str_to_int64 (&s[2], 16, 0, G_MAXUINT, -1);
if (v64 == -1) {
ret = FALSE;
break;
}
value |= (int) v64;
} else {
flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (class), s);
if (!flags_value) {
ret = FALSE;
break;
}
value |= flags_value->value;
}
}
s = s_end;
}
} else
g_return_val_if_reached (FALSE);
NM_SET_OUT (err_token, !ret && s[0] ? g_strdup (s) : NULL);
NM_SET_OUT (out_value, ret ? value : 0);
g_type_class_unref (class);
return ret;
}
/**
* nm_utils_enum_get_values:
* @type: the %GType of the enum
* @from: the first element to be returned
* @to: the last element to be returned
*
* Returns the list of possible values for a given enum.
*
* Returns: (transfer container): a NULL-terminated dynamically-allocated array of static strings
* or %NULL on error
*
* Since: 1.2
*/
const char **nm_utils_enum_get_values (GType type, gint from, gint to)
{
GTypeClass *class;
GPtrArray *array;
gint i;
char sbuf[64];
class = g_type_class_ref (type);
array = g_ptr_array_new ();
if (G_IS_ENUM_CLASS (class)) {
GEnumClass *enum_class = G_ENUM_CLASS (class);
GEnumValue *enum_value;
for (i = 0; i < enum_class->n_values; i++) {
enum_value = &enum_class->values[i];
if (enum_value->value >= from && enum_value->value <= to) {
if (_enum_is_valid_enum_nick (enum_value->value_nick))
g_ptr_array_add (array, (gpointer) enum_value->value_nick);
else
g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "%d", enum_value->value)));
}
}
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsClass *flags_class = G_FLAGS_CLASS (class);
GFlagsValue *flags_value;
for (i = 0; i < flags_class->n_values; i++) {
flags_value = &flags_class->values[i];
if (flags_value->value >= from && flags_value->value <= to) {
if (_enum_is_valid_flags_nick (flags_value->value_nick))
g_ptr_array_add (array, (gpointer) flags_value->value_nick);
else
g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "0x%x", (unsigned) flags_value->value)));
}
}
} else {
g_type_class_unref (class);
g_ptr_array_free (array, TRUE);
g_return_val_if_reached (NULL);
}
g_type_class_unref (class);
g_ptr_array_add (array, NULL);
return (const char **) g_ptr_array_free (array, FALSE);
}
#if WITH_JANSSON
/**
* nm_utils_is_json_object:

View file

@ -5200,7 +5200,7 @@ static void test_nm_utils_enum (void)
test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_67, "67");
test_nm_utils_enum_to_str_do (bool_enum, NM_TEST_GENERAL_BOOL_ENUM_46, "64");
test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "");
test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_NONE, "none");
test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_BAZ, "baz");
test_nm_utils_enum_to_str_do (meta_flags, NM_TEST_GENERAL_META_FLAGS_FOO |
NM_TEST_GENERAL_META_FLAGS_BAR |

View file

@ -10,6 +10,8 @@ clients/cli/nmcli.c
clients/cli/polkit-agent.c
clients/cli/settings.c
clients/cli/utils.c
clients/common/nm-client-utils.c
clients/common/nm-meta-setting-desc.c
clients/common/nm-polkit-listener.c
clients/common/nm-secret-agent-simple.c
clients/common/nm-vpn-helpers.c

341
shared/nm-meta-setting.c Normal file
View file

@ -0,0 +1,341 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-meta-setting.h"
#include "nm-setting-8021x.h"
#include "nm-setting-adsl.h"
#include "nm-setting-bluetooth.h"
#include "nm-setting-bond.h"
#include "nm-setting-bridge.h"
#include "nm-setting-bridge-port.h"
#include "nm-setting-cdma.h"
#include "nm-setting-connection.h"
#include "nm-setting-dcb.h"
#include "nm-setting-dummy.h"
#include "nm-setting-generic.h"
#include "nm-setting-gsm.h"
#include "nm-setting-infiniband.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-ip-config.h"
#include "nm-setting-ip-tunnel.h"
#include "nm-setting-macsec.h"
#include "nm-setting-macvlan.h"
#include "nm-setting-olpc-mesh.h"
#include "nm-setting-ppp.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-proxy.h"
#include "nm-setting-serial.h"
#include "nm-setting-team.h"
#include "nm-setting-team-port.h"
#include "nm-setting-tun.h"
#include "nm-setting-user.h"
#include "nm-setting-vlan.h"
#include "nm-setting-vpn.h"
#include "nm-setting-vxlan.h"
#include "nm-setting-wimax.h"
#include "nm-setting-wired.h"
#include "nm-setting-wireless.h"
#include "nm-setting-wireless-security.h"
/*****************************************************************************/
const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[] = {
[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT] = {
.setting_key = NM_SETTING_802_1X_CA_CERT,
.scheme_func = nm_setting_802_1x_get_ca_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_ca_cert_path,
.blob_func = nm_setting_802_1x_get_ca_cert_blob,
.uri_func = nm_setting_802_1x_get_ca_cert_uri,
.passwd_func = nm_setting_802_1x_get_ca_cert_password,
.pwflag_func = nm_setting_802_1x_get_ca_cert_password_flags,
.file_suffix = "ca-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] = {
.setting_key = NM_SETTING_802_1X_PHASE2_CA_CERT,
.scheme_func = nm_setting_802_1x_get_phase2_ca_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_phase2_ca_cert_path,
.blob_func = nm_setting_802_1x_get_phase2_ca_cert_blob,
.uri_func = nm_setting_802_1x_get_phase2_ca_cert_uri,
.passwd_func = nm_setting_802_1x_get_phase2_ca_cert_password,
.pwflag_func = nm_setting_802_1x_get_phase2_ca_cert_password_flags,
.file_suffix = "inner-ca-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT] = {
.setting_key = NM_SETTING_802_1X_CLIENT_CERT,
.scheme_func = nm_setting_802_1x_get_client_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_client_cert_path,
.blob_func = nm_setting_802_1x_get_client_cert_blob,
.uri_func = nm_setting_802_1x_get_client_cert_uri,
.passwd_func = nm_setting_802_1x_get_client_cert_password,
.pwflag_func = nm_setting_802_1x_get_client_cert_password_flags,
.file_suffix = "client-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] = {
.setting_key = NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
.scheme_func = nm_setting_802_1x_get_phase2_client_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_phase2_client_cert_path,
.blob_func = nm_setting_802_1x_get_phase2_client_cert_blob,
.uri_func = nm_setting_802_1x_get_phase2_client_cert_uri,
.passwd_func = nm_setting_802_1x_get_phase2_client_cert_password,
.pwflag_func = nm_setting_802_1x_get_phase2_client_cert_password_flags,
.file_suffix = "inner-client-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY] = {
.setting_key = NM_SETTING_802_1X_PRIVATE_KEY,
.scheme_func = nm_setting_802_1x_get_private_key_scheme,
.format_func = nm_setting_802_1x_get_private_key_format,
.path_func = nm_setting_802_1x_get_private_key_path,
.blob_func = nm_setting_802_1x_get_private_key_blob,
.uri_func = nm_setting_802_1x_get_private_key_uri,
.passwd_func = nm_setting_802_1x_get_private_key_password,
.pwflag_func = nm_setting_802_1x_get_private_key_password_flags,
.file_suffix = "private-key",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY] = {
.setting_key = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
.scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme,
.format_func = nm_setting_802_1x_get_phase2_private_key_format,
.path_func = nm_setting_802_1x_get_phase2_private_key_path,
.blob_func = nm_setting_802_1x_get_phase2_private_key_blob,
.uri_func = nm_setting_802_1x_get_phase2_private_key_uri,
.passwd_func = nm_setting_802_1x_get_phase2_private_key_password,
.pwflag_func = nm_setting_802_1x_get_phase2_private_key_password_flags,
.file_suffix = "inner-private-key",
},
[NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN] = { NULL },
};
/*****************************************************************************/
const NMMetaSettingInfo nm_meta_setting_infos[] = {
[NM_META_SETTING_TYPE_802_1X] = {
.meta_type = NM_META_SETTING_TYPE_802_1X,
.setting_name = N_ (NM_SETTING_802_1X_SETTING_NAME),
.get_setting_gtype = nm_setting_802_1x_get_type,
},
[NM_META_SETTING_TYPE_ADSL] = {
.meta_type = NM_META_SETTING_TYPE_ADSL,
.setting_name = N_ (NM_SETTING_ADSL_SETTING_NAME),
.get_setting_gtype = nm_setting_adsl_get_type,
},
[NM_META_SETTING_TYPE_BLUETOOTH] = {
.meta_type = NM_META_SETTING_TYPE_BLUETOOTH,
.setting_name = N_ (NM_SETTING_BLUETOOTH_SETTING_NAME),
.get_setting_gtype = nm_setting_bluetooth_get_type,
},
[NM_META_SETTING_TYPE_BOND] = {
.meta_type = NM_META_SETTING_TYPE_BOND,
.setting_name = N_ (NM_SETTING_BOND_SETTING_NAME),
.get_setting_gtype = nm_setting_bond_get_type,
},
[NM_META_SETTING_TYPE_BRIDGE] = {
.meta_type = NM_META_SETTING_TYPE_BRIDGE,
.setting_name = N_ (NM_SETTING_BRIDGE_SETTING_NAME),
.get_setting_gtype = nm_setting_bridge_get_type,
},
[NM_META_SETTING_TYPE_BRIDGE_PORT] = {
.meta_type = NM_META_SETTING_TYPE_BRIDGE_PORT,
.setting_name = N_ (NM_SETTING_BRIDGE_PORT_SETTING_NAME),
.get_setting_gtype = nm_setting_bridge_port_get_type,
},
[NM_META_SETTING_TYPE_CDMA] = {
.meta_type = NM_META_SETTING_TYPE_CDMA,
.setting_name = N_ (NM_SETTING_CDMA_SETTING_NAME),
.get_setting_gtype = nm_setting_cdma_get_type,
},
[NM_META_SETTING_TYPE_CONNECTION] = {
.meta_type = NM_META_SETTING_TYPE_CONNECTION,
.setting_name = N_ (NM_SETTING_CONNECTION_SETTING_NAME),
.get_setting_gtype = nm_setting_connection_get_type,
},
[NM_META_SETTING_TYPE_DCB] = {
.meta_type = NM_META_SETTING_TYPE_DCB,
.setting_name = N_ (NM_SETTING_DCB_SETTING_NAME),
.get_setting_gtype = nm_setting_dcb_get_type,
},
[NM_META_SETTING_TYPE_DUMMY] = {
.meta_type = NM_META_SETTING_TYPE_DUMMY,
.setting_name = N_ (NM_SETTING_DUMMY_SETTING_NAME),
.get_setting_gtype = nm_setting_dummy_get_type,
},
[NM_META_SETTING_TYPE_GSM] = {
.meta_type = NM_META_SETTING_TYPE_GSM,
.setting_name = N_ (NM_SETTING_GSM_SETTING_NAME),
.get_setting_gtype = nm_setting_gsm_get_type,
},
[NM_META_SETTING_TYPE_INFINIBAND] = {
.meta_type = NM_META_SETTING_TYPE_INFINIBAND,
.setting_name = N_ (NM_SETTING_INFINIBAND_SETTING_NAME),
.get_setting_gtype = nm_setting_infiniband_get_type,
},
[NM_META_SETTING_TYPE_IP4_CONFIG] = {
.meta_type = NM_META_SETTING_TYPE_IP4_CONFIG,
.setting_name = N_ (NM_SETTING_IP4_CONFIG_SETTING_NAME),
.get_setting_gtype = nm_setting_ip4_config_get_type,
},
[NM_META_SETTING_TYPE_IP6_CONFIG] = {
.meta_type = NM_META_SETTING_TYPE_IP6_CONFIG,
.setting_name = N_ (NM_SETTING_IP6_CONFIG_SETTING_NAME),
.get_setting_gtype = nm_setting_ip6_config_get_type,
},
[NM_META_SETTING_TYPE_IP_TUNNEL] = {
.meta_type = NM_META_SETTING_TYPE_IP_TUNNEL,
.setting_name = N_ (NM_SETTING_IP_TUNNEL_SETTING_NAME),
.get_setting_gtype = nm_setting_ip_tunnel_get_type,
},
[NM_META_SETTING_TYPE_MACSEC] = {
.meta_type = NM_META_SETTING_TYPE_MACSEC,
.setting_name = N_ (NM_SETTING_MACSEC_SETTING_NAME),
.get_setting_gtype = nm_setting_macsec_get_type,
},
[NM_META_SETTING_TYPE_MACVLAN] = {
.meta_type = NM_META_SETTING_TYPE_MACVLAN,
.setting_name = N_ (NM_SETTING_MACVLAN_SETTING_NAME),
.get_setting_gtype = nm_setting_macvlan_get_type,
},
[NM_META_SETTING_TYPE_OLPC_MESH] = {
.meta_type = NM_META_SETTING_TYPE_OLPC_MESH,
.setting_name = N_ (NM_SETTING_OLPC_MESH_SETTING_NAME),
.get_setting_gtype = nm_setting_olpc_mesh_get_type,
},
[NM_META_SETTING_TYPE_PPPOE] = {
.meta_type = NM_META_SETTING_TYPE_PPPOE,
.setting_name = N_ (NM_SETTING_PPPOE_SETTING_NAME),
.get_setting_gtype = nm_setting_pppoe_get_type,
},
[NM_META_SETTING_TYPE_PPP] = {
.meta_type = NM_META_SETTING_TYPE_PPP,
.setting_name = N_ (NM_SETTING_PPP_SETTING_NAME),
.get_setting_gtype = nm_setting_ppp_get_type,
},
[NM_META_SETTING_TYPE_PROXY] = {
.meta_type = NM_META_SETTING_TYPE_PROXY,
.setting_name = N_ (NM_SETTING_PROXY_SETTING_NAME),
.get_setting_gtype = nm_setting_proxy_get_type,
},
[NM_META_SETTING_TYPE_SERIAL] = {
.meta_type = NM_META_SETTING_TYPE_SERIAL,
.setting_name = N_ (NM_SETTING_SERIAL_SETTING_NAME),
.get_setting_gtype = nm_setting_serial_get_type,
},
[NM_META_SETTING_TYPE_TEAM] = {
.meta_type = NM_META_SETTING_TYPE_TEAM,
.setting_name = N_ (NM_SETTING_TEAM_SETTING_NAME),
.get_setting_gtype = nm_setting_team_get_type,
},
[NM_META_SETTING_TYPE_TEAM_PORT] = {
.meta_type = NM_META_SETTING_TYPE_TEAM_PORT,
.setting_name = N_ (NM_SETTING_TEAM_PORT_SETTING_NAME),
.get_setting_gtype = nm_setting_team_port_get_type,
},
[NM_META_SETTING_TYPE_TUN] = {
.meta_type = NM_META_SETTING_TYPE_TUN,
.setting_name = N_ (NM_SETTING_TUN_SETTING_NAME),
.get_setting_gtype = nm_setting_tun_get_type,
},
[NM_META_SETTING_TYPE_USER] = {
.meta_type = NM_META_SETTING_TYPE_USER,
.setting_name = N_ (NM_SETTING_USER_SETTING_NAME),
.get_setting_gtype = nm_setting_user_get_type,
},
[NM_META_SETTING_TYPE_VLAN] = {
.meta_type = NM_META_SETTING_TYPE_VLAN,
.setting_name = N_ (NM_SETTING_VLAN_SETTING_NAME),
.get_setting_gtype = nm_setting_vlan_get_type,
},
[NM_META_SETTING_TYPE_VPN] = {
.meta_type = NM_META_SETTING_TYPE_VPN,
.setting_name = N_ (NM_SETTING_VPN_SETTING_NAME),
.get_setting_gtype = nm_setting_vpn_get_type,
},
[NM_META_SETTING_TYPE_VXLAN] = {
.meta_type = NM_META_SETTING_TYPE_VXLAN,
.setting_name = N_ (NM_SETTING_VXLAN_SETTING_NAME),
.get_setting_gtype = nm_setting_vxlan_get_type,
},
[NM_META_SETTING_TYPE_WIMAX] = {
.meta_type = NM_META_SETTING_TYPE_WIMAX,
.setting_name = N_ (NM_SETTING_WIMAX_SETTING_NAME),
.get_setting_gtype = nm_setting_wimax_get_type,
},
[NM_META_SETTING_TYPE_WIRED] = {
.meta_type = NM_META_SETTING_TYPE_WIRED,
.setting_name = N_ (NM_SETTING_WIRED_SETTING_NAME),
.get_setting_gtype = nm_setting_wired_get_type,
},
[NM_META_SETTING_TYPE_WIRELESS] = {
.meta_type = NM_META_SETTING_TYPE_WIRELESS,
.setting_name = N_ (NM_SETTING_WIRELESS_SETTING_NAME),
.get_setting_gtype = nm_setting_wireless_get_type,
},
[NM_META_SETTING_TYPE_WIRELESS_SECURITY] = {
.meta_type = NM_META_SETTING_TYPE_WIRELESS_SECURITY,
.setting_name = N_ (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME),
.get_setting_gtype = nm_setting_wireless_security_get_type,
},
[NM_META_SETTING_TYPE_UNKNOWN] = {
.meta_type = NM_META_SETTING_TYPE_UNKNOWN,
.setting_name = NULL,
},
};
const NMMetaSettingInfo *
nm_meta_setting_infos_by_name (const char *name)
{
int i;
if (name) {
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
if (nm_streq (nm_meta_setting_infos[i].setting_name, name))
return &nm_meta_setting_infos[i];
}
}
return NULL;
}
const NMMetaSettingInfo *
nm_meta_setting_infos_by_gtype (GType gtype)
{
int i;
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
if (nm_meta_setting_infos[i].get_setting_gtype () == gtype)
return &nm_meta_setting_infos[i];
}
return NULL;
}
/*****************************************************************************/

View file

@ -19,13 +19,26 @@
* Copyright 2017 Red Hat, Inc.
*/
#ifndef __NM_SETTING_METADATA_H__
#define __NM_SETTING_METADATA_H__
#ifndef __NM_META_SETTING_H__
#define __NM_META_SETTING_H__
#include "nm-setting-8021x.h"
/*****************************************************************************/
typedef enum {
NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY,
NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN,
_NM_SETTING_802_1X_SCHEME_TYPE_NUM = NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN,
} NMSetting8021xSchemeType;
typedef struct {
const char *setting_key;
NMSetting8021xCKScheme (*scheme_func) (NMSetting8021x *setting);
@ -38,19 +51,61 @@ typedef struct {
const char *file_suffix;
} NMSetting8021xSchemeVtable;
enum {
NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT,
NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY,
NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY,
NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN,
};
extern const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN + 1];
extern const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[_NM_SETTING_802_1X_SCHEME_TYPE_NUM + 1];
/*****************************************************************************/
#endif /* __NM_SETTING_METADATA_H__ */
typedef enum {
NM_META_SETTING_TYPE_802_1X,
NM_META_SETTING_TYPE_ADSL,
NM_META_SETTING_TYPE_BLUETOOTH,
NM_META_SETTING_TYPE_BOND,
NM_META_SETTING_TYPE_BRIDGE,
NM_META_SETTING_TYPE_BRIDGE_PORT,
NM_META_SETTING_TYPE_CDMA,
NM_META_SETTING_TYPE_CONNECTION,
NM_META_SETTING_TYPE_DCB,
NM_META_SETTING_TYPE_DUMMY,
NM_META_SETTING_TYPE_GSM,
NM_META_SETTING_TYPE_INFINIBAND,
NM_META_SETTING_TYPE_IP4_CONFIG,
NM_META_SETTING_TYPE_IP6_CONFIG,
NM_META_SETTING_TYPE_IP_TUNNEL,
NM_META_SETTING_TYPE_MACSEC,
NM_META_SETTING_TYPE_MACVLAN,
NM_META_SETTING_TYPE_OLPC_MESH,
NM_META_SETTING_TYPE_PPP,
NM_META_SETTING_TYPE_PPPOE,
NM_META_SETTING_TYPE_PROXY,
NM_META_SETTING_TYPE_SERIAL,
NM_META_SETTING_TYPE_TEAM,
NM_META_SETTING_TYPE_TEAM_PORT,
NM_META_SETTING_TYPE_TUN,
NM_META_SETTING_TYPE_USER,
NM_META_SETTING_TYPE_VLAN,
NM_META_SETTING_TYPE_VPN,
NM_META_SETTING_TYPE_VXLAN,
NM_META_SETTING_TYPE_WIMAX,
NM_META_SETTING_TYPE_WIRED,
NM_META_SETTING_TYPE_WIRELESS,
NM_META_SETTING_TYPE_WIRELESS_SECURITY,
NM_META_SETTING_TYPE_UNKNOWN,
_NM_META_SETTING_TYPE_NUM = NM_META_SETTING_TYPE_UNKNOWN,
} NMMetaSettingType;
typedef struct {
NMMetaSettingType meta_type;
const char *setting_name;
GType (*get_setting_gtype) (void);
} NMMetaSettingInfo;
extern const NMMetaSettingInfo nm_meta_setting_infos[_NM_META_SETTING_TYPE_NUM + 1];
const NMMetaSettingInfo *nm_meta_setting_infos_by_name (const char *name);
const NMMetaSettingInfo *nm_meta_setting_infos_by_gtype (GType gtype);
/*****************************************************************************/
#endif /* __NM_META_SETTING_H__ */

View file

@ -1,104 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-setting-metadata.h"
/*****************************************************************************/
const NMSetting8021xSchemeVtable nm_setting_8021x_scheme_vtable[] = {
[NM_SETTING_802_1X_SCHEME_TYPE_CA_CERT] = {
.setting_key = NM_SETTING_802_1X_CA_CERT,
.scheme_func = nm_setting_802_1x_get_ca_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_ca_cert_path,
.blob_func = nm_setting_802_1x_get_ca_cert_blob,
.uri_func = nm_setting_802_1x_get_ca_cert_uri,
.passwd_func = nm_setting_802_1x_get_ca_cert_password,
.pwflag_func = nm_setting_802_1x_get_ca_cert_password_flags,
.file_suffix = "ca-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CA_CERT] = {
.setting_key = NM_SETTING_802_1X_PHASE2_CA_CERT,
.scheme_func = nm_setting_802_1x_get_phase2_ca_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_phase2_ca_cert_path,
.blob_func = nm_setting_802_1x_get_phase2_ca_cert_blob,
.uri_func = nm_setting_802_1x_get_phase2_ca_cert_uri,
.passwd_func = nm_setting_802_1x_get_phase2_ca_cert_password,
.pwflag_func = nm_setting_802_1x_get_phase2_ca_cert_password_flags,
.file_suffix = "inner-ca-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_CLIENT_CERT] = {
.setting_key = NM_SETTING_802_1X_CLIENT_CERT,
.scheme_func = nm_setting_802_1x_get_client_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_client_cert_path,
.blob_func = nm_setting_802_1x_get_client_cert_blob,
.uri_func = nm_setting_802_1x_get_client_cert_uri,
.passwd_func = nm_setting_802_1x_get_client_cert_password,
.pwflag_func = nm_setting_802_1x_get_client_cert_password_flags,
.file_suffix = "client-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_CLIENT_CERT] = {
.setting_key = NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
.scheme_func = nm_setting_802_1x_get_phase2_client_cert_scheme,
.format_func = NULL,
.path_func = nm_setting_802_1x_get_phase2_client_cert_path,
.blob_func = nm_setting_802_1x_get_phase2_client_cert_blob,
.uri_func = nm_setting_802_1x_get_phase2_client_cert_uri,
.passwd_func = nm_setting_802_1x_get_phase2_client_cert_password,
.pwflag_func = nm_setting_802_1x_get_phase2_client_cert_password_flags,
.file_suffix = "inner-client-cert",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PRIVATE_KEY] = {
.setting_key = NM_SETTING_802_1X_PRIVATE_KEY,
.scheme_func = nm_setting_802_1x_get_private_key_scheme,
.format_func = nm_setting_802_1x_get_private_key_format,
.path_func = nm_setting_802_1x_get_private_key_path,
.blob_func = nm_setting_802_1x_get_private_key_blob,
.uri_func = nm_setting_802_1x_get_private_key_uri,
.passwd_func = nm_setting_802_1x_get_private_key_password,
.pwflag_func = nm_setting_802_1x_get_private_key_password_flags,
.file_suffix = "private-key",
},
[NM_SETTING_802_1X_SCHEME_TYPE_PHASE2_PRIVATE_KEY] = {
.setting_key = NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
.scheme_func = nm_setting_802_1x_get_phase2_private_key_scheme,
.format_func = nm_setting_802_1x_get_phase2_private_key_format,
.path_func = nm_setting_802_1x_get_phase2_private_key_path,
.blob_func = nm_setting_802_1x_get_phase2_private_key_blob,
.uri_func = nm_setting_802_1x_get_phase2_private_key_uri,
.passwd_func = nm_setting_802_1x_get_phase2_private_key_password,
.pwflag_func = nm_setting_802_1x_get_phase2_private_key_password_flags,
.file_suffix = "inner-private-key",
},
[NM_SETTING_802_1X_SCHEME_TYPE_UNKNOWN] = { NULL },
};
/*****************************************************************************/

View file

@ -0,0 +1,346 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2017 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-enum-utils.h"
/*****************************************************************************/
#define IS_FLAGS_SEPARATOR(ch) (NM_IN_SET ((ch), ' ', '\t', ',', '\n', '\r'))
static gboolean
_is_hex_string (const char *str)
{
return str[0] == '0'
&& str[1] == 'x'
&& str[2]
&& NM_STRCHAR_ALL (&str[2], ch, g_ascii_isxdigit (ch));
}
static gboolean
_is_dec_string (const char *str)
{
return str[0]
&& NM_STRCHAR_ALL (&str[0], ch, g_ascii_isdigit (ch));
}
static gboolean
_enum_is_valid_enum_nick (const char *str)
{
return str[0]
&& !NM_STRCHAR_ANY (str, ch, g_ascii_isspace (ch))
&& !_is_dec_string (str)
&& !_is_hex_string (str);
}
static gboolean
_enum_is_valid_flags_nick (const char *str)
{
return str[0]
&& !NM_STRCHAR_ANY (str, ch, IS_FLAGS_SEPARATOR (ch))
&& !_is_dec_string (str)
&& !_is_hex_string (str);
}
char *
_nm_utils_enum_to_str_full (GType type,
int value,
const char *flags_separator)
{
GTypeClass *class;
char *ret;
if ( flags_separator
&& ( !flags_separator[0]
|| NM_STRCHAR_ANY (flags_separator, ch, !IS_FLAGS_SEPARATOR (ch))))
g_return_val_if_reached (NULL);
class = g_type_class_ref (type);
if (G_IS_ENUM_CLASS (class)) {
GEnumValue *enum_value;
enum_value = g_enum_get_value (G_ENUM_CLASS (class), value);
if ( !enum_value
|| !_enum_is_valid_enum_nick (enum_value->value_nick))
ret = g_strdup_printf ("%d", value);
else
ret = strdup (enum_value->value_nick);
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsValue *flags_value;
GString *str = g_string_new ("");
unsigned uvalue = (unsigned) value;
flags_separator = flags_separator ?: " ";
do {
flags_value = g_flags_get_first_value (G_FLAGS_CLASS (class), uvalue);
if (str->len)
g_string_append (str, flags_separator);
if ( !flags_value
|| !_enum_is_valid_flags_nick (flags_value->value_nick)) {
if (uvalue)
g_string_append_printf (str, "0x%x", uvalue);
break;
}
g_string_append (str, flags_value->value_nick);
uvalue &= ~flags_value->value;
} while (uvalue);
ret = g_string_free (str, FALSE);
} else
g_return_val_if_reached (NULL);
g_type_class_unref (class);
return ret;
}
/**
* nm_utils_enum_to_str:
* @type: the %GType of the enum
* @value: the value to be translated
*
* Converts an enum value to its string representation. If the enum is a
* %G_TYPE_FLAGS the function returns a comma-separated list of matching values.
* If the value has no corresponding string representation, it is converted
* to a number. For enums it is converted to a decimal number, for flags
* to an (unsigned) hex number.
*
* Returns: a newly allocated string or %NULL
*
* Since: 1.2
*/
char *
nm_utils_enum_to_str (GType type, int value)
{
return _nm_utils_enum_to_str_full (type, value, ", ");
}
/**
* nm_utils_enum_from_str:
* @type: the %GType of the enum
* @str: the input string
* @out_value: (out) (allow-none): the output value
* @err_token: (out) (allow-none) (transfer full): location to store the first unrecognized token
*
* Converts a string to the matching enum value.
*
* If the enum is a %G_TYPE_FLAGS the function returns the logical OR of values
* matching the comma-separated tokens in the string; if an unknown token is found
* the function returns %FALSE and stores a pointer to a newly allocated string
* containing the unrecognized token in @err_token.
*
* Returns: %TRUE if the conversion was successful, %FALSE otherwise
*
* Since: 1.2
*/
gboolean
nm_utils_enum_from_str (GType type, const char *str,
int *out_value, char **err_token)
{
return _nm_utils_enum_from_str_full (type, str, out_value, err_token, NULL);
}
static const NMUtilsEnumValueInfo *
_find_value_info (const NMUtilsEnumValueInfo *value_infos, const char *needle)
{
if (value_infos) {
for (; value_infos->nick; value_infos++) {
if (nm_streq (needle, value_infos->nick))
return value_infos;
}
}
return NULL;
}
gboolean
_nm_utils_enum_from_str_full (GType type,
const char *str,
int *out_value,
char **err_token,
const NMUtilsEnumValueInfo *value_infos)
{
GTypeClass *class;
gboolean ret = FALSE;
int value = 0;
gs_free char *str_clone = NULL;
char *s;
gint64 v64;
const NMUtilsEnumValueInfo *nick;
g_return_val_if_fail (str, FALSE);
str_clone = strdup (str);
s = nm_str_skip_leading_spaces (str_clone);
g_strchomp (s);
class = g_type_class_ref (type);
if (G_IS_ENUM_CLASS (class)) {
GEnumValue *enum_value;
if (s[0]) {
if (_is_hex_string (s)) {
v64 = _nm_utils_ascii_str_to_int64 (s, 16, 0, G_MAXUINT, -1);
if (v64 != -1) {
value = (int) v64;
ret = TRUE;
}
} else if (_is_dec_string (s)) {
v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT, -1);
if (v64 != -1) {
value = (int) v64;
ret = TRUE;
}
} else {
enum_value = g_enum_get_value_by_nick (G_ENUM_CLASS (class), s);
if (enum_value) {
value = enum_value->value;
ret = TRUE;
} else {
nick = _find_value_info (value_infos, s);
if (nick) {
value = nick->value;
ret = TRUE;
}
}
}
}
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsValue *flags_value;
unsigned uvalue = 0;
ret = TRUE;
while (s[0]) {
char *s_end;
for (s_end = s; s_end[0]; s_end++) {
if (IS_FLAGS_SEPARATOR (s_end[0])) {
s_end[0] = '\0';
s_end++;
break;
}
}
if (s[0]) {
if (_is_hex_string (s)) {
v64 = _nm_utils_ascii_str_to_int64 (&s[2], 16, 0, G_MAXUINT, -1);
if (v64 == -1) {
ret = FALSE;
break;
}
uvalue |= (unsigned) v64;
} else if (_is_dec_string (s)) {
v64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXUINT, -1);
if (v64 == -1) {
ret = FALSE;
break;
}
uvalue |= (unsigned) v64;
} else {
flags_value = g_flags_get_value_by_nick (G_FLAGS_CLASS (class), s);
if (flags_value)
uvalue |= flags_value->value;
else {
nick = _find_value_info (value_infos, s);
if (nick)
uvalue = (unsigned) nick->value;
else {
ret = FALSE;
break;
}
}
}
}
s = s_end;
}
value = (int) uvalue;
} else
g_return_val_if_reached (FALSE);
NM_SET_OUT (err_token, !ret && s[0] ? g_strdup (s) : NULL);
NM_SET_OUT (out_value, ret ? value : 0);
g_type_class_unref (class);
return ret;
}
/**
* nm_utils_enum_get_values:
* @type: the %GType of the enum
* @from: the first element to be returned
* @to: the last element to be returned
*
* Returns the list of possible values for a given enum.
*
* Returns: (transfer container): a NULL-terminated dynamically-allocated array of static strings
* or %NULL on error
*
* Since: 1.2
*/
const char **nm_utils_enum_get_values (GType type, gint from, gint to)
{
GTypeClass *class;
GPtrArray *array;
gint i;
char sbuf[64];
class = g_type_class_ref (type);
array = g_ptr_array_new ();
if (G_IS_ENUM_CLASS (class)) {
GEnumClass *enum_class = G_ENUM_CLASS (class);
GEnumValue *enum_value;
for (i = 0; i < enum_class->n_values; i++) {
enum_value = &enum_class->values[i];
if (enum_value->value >= from && enum_value->value <= to) {
if (_enum_is_valid_enum_nick (enum_value->value_nick))
g_ptr_array_add (array, (gpointer) enum_value->value_nick);
else
g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "%d", enum_value->value)));
}
}
} else if (G_IS_FLAGS_CLASS (class)) {
GFlagsClass *flags_class = G_FLAGS_CLASS (class);
GFlagsValue *flags_value;
for (i = 0; i < flags_class->n_values; i++) {
flags_value = &flags_class->values[i];
if (flags_value->value >= from && flags_value->value <= to) {
if (_enum_is_valid_flags_nick (flags_value->value_nick))
g_ptr_array_add (array, (gpointer) flags_value->value_nick);
else
g_ptr_array_add (array, (gpointer) g_intern_string (nm_sprintf_buf (sbuf, "0x%x", (unsigned) flags_value->value)));
}
}
} else {
g_type_class_unref (class);
g_ptr_array_free (array, TRUE);
g_return_val_if_reached (NULL);
}
g_type_class_unref (class);
g_ptr_array_add (array, NULL);
return (const char **) g_ptr_array_free (array, FALSE);
}

View file

@ -0,0 +1,47 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager -- Network link manager
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2017 Red Hat, Inc.
*/
#ifndef __NM_ENUM_UTILS_H__
#define __NM_ENUM_UTILS_H__
/*****************************************************************************/
typedef struct _NMUtilsEnumValueInfo {
/* currently, this is only used for _nm_utils_enum_from_str_full() to
* declare additional aliases for values. */
const char *nick;
int value;
} NMUtilsEnumValueInfo;
char *_nm_utils_enum_to_str_full (GType type, int value, const char *sep);
gboolean _nm_utils_enum_from_str_full (GType type,
const char *str,
int *out_value,
char **err_token,
const NMUtilsEnumValueInfo *value_infos);
char *nm_utils_enum_to_str (GType type, int value);
gboolean nm_utils_enum_from_str (GType type, const char *str, int *out_value, char **err_token);
const char **nm_utils_enum_get_values (GType type, gint from, gint to);
/*****************************************************************************/
#endif /* __NM_ENUM_UTILS_H__ */

View file

@ -55,6 +55,14 @@ _nm_auto_unset_gvalue_impl (GValue *v)
}
#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl)
static inline void
_nm_auto_unref_gtypeclass (GTypeClass **v)
{
if (v && *v)
g_type_class_unref (*v);
}
#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
static inline void
_nm_auto_free_gstring_impl (GString **str)
{

View file

@ -62,10 +62,12 @@ gint _nm_utils_ascii_str_to_bool (const char *str,
* error reason. Depending on the usage, this might indicate a bug because
* usually the target object should stay alive as long as there are pending
* operations.
* @NM_UTILS_ERROR_INVALID_ARGUMENT: invalid argument.
*/
typedef enum {
NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
NM_UTILS_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/
} NMUtilsError;
#define NM_UTILS_ERROR (nm_utils_error_quark ())

View file

@ -32,6 +32,7 @@
#include <unistd.h>
#include <stdio.h>
#include "nm-utils/nm-enum-utils.h"
#include "nm-manager.h"
#include "nm-setting-connection.h"
#include "nm-setting-wired.h"
@ -47,7 +48,7 @@
#include "nm-utils.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-setting-metadata.h"
#include "nm-meta-setting.h"
#include "nms-ifcfg-rh-common.h"
#include "nms-ifcfg-rh-reader.h"

View file

@ -31,7 +31,7 @@
#include "settings/nm-settings-plugin.h"
#include "nm-core-internal.h"
#include "NetworkManagerUtils.h"
#include "nm-setting-metadata.h"
#include "nm-meta-setting.h"
#include "nms-ifnet-net-utils.h"
#include "nms-ifnet-wpa-parser.h"