merge: nmcli: sort connections and add colors to nmcli output (bgo #738613)

https://bugzilla.gnome.org/show_bug.cgi?id=738613
This commit is contained in:
Jiří Klimeš 2015-02-23 09:37:55 +01:00
commit afe086e763
8 changed files with 658 additions and 141 deletions

View file

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
#include "config.h"
@ -250,7 +250,8 @@ usage (void)
{
g_printerr (_("Usage: nmcli connection { COMMAND | help }\n\n"
"COMMAND := { show | up | down | add | modify | edit | delete | reload | load }\n\n"
" show [--active] [[--show-secrets] [id | uuid | path | apath] <ID>] ...\n\n"
" show [--active] [--order <order spec>]\n"
" show [--active] [--show-secrets] [id | uuid | path | apath] <ID> ...\n\n"
#if WITH_WIMAX
" up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>] [nsp <name>] [passwd-file <file with passwords>]\n\n"
#else
@ -271,12 +272,12 @@ usage_connection_show (void)
{
g_printerr (_("Usage: nmcli connection show { ARGUMENTS | help }\n"
"\n"
"ARGUMENTS := [--active]\n"
"ARGUMENTS := [--active] [--order <order spec>]\n"
"\n"
"List in-memory and on-disk connection profiles, some of which may also be\n"
"active if a device is using that connection profile. Without a parameter, all\n"
"profiles are listed. When --active option is specified, only the active\n"
"profiles are shown.\n"
"profiles are shown. --order allows custom connection ordering (see manual page).\n"
"\n"
"ARGUMENTS := [--active] [--show-secrets] [id | uuid | path | apath] <ID> ...\n"
"\n"
@ -763,10 +764,8 @@ find_active_connection (const GPtrArray *active_cons,
}
static void
fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
fill_output_connection (NMConnection *connection, NmCli *nmc, gboolean active_only)
{
NMConnection *connection = (NMConnection *) data;
NmCli *nmc = (NmCli *) user_data;
NMSettingConnection *s_con;
guint64 timestamp;
time_t timestamp_real;
@ -777,6 +776,7 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
NMActiveConnection *ac = NULL;
const char *ac_path = NULL;
const char *ac_state = NULL;
NMActiveConnectionState ac_state_int;
char *ac_dev = NULL;
s_con = nm_connection_get_setting_connection (connection);
@ -788,7 +788,8 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
if (ac) {
ac_path = nm_object_get_path (NM_OBJECT (ac));
ac_state = active_connection_state_to_string (nm_active_connection_get_state (ac));
ac_state_int = nm_active_connection_get_state (ac);
ac_state = active_connection_state_to_string (ac_state_int);
ac_dev = get_ac_device_string (ac);
}
@ -805,6 +806,16 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
arr = nmc_dup_fields_array (nmc_fields_con_show,
sizeof (nmc_fields_con_show),
0);
/* Show active connections in color */
if (ac) {
if (ac_state_int == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
set_val_color_all (arr, NMC_TERM_COLOR_YELLOW);
else if (ac_state_int == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
set_val_color_all (arr, NMC_TERM_COLOR_GREEN);
else if (ac_state_int > NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
set_val_color_all (arr, NMC_TERM_COLOR_RED);
}
set_val_strc (arr, 0, nm_setting_connection_get_id (s_con));
set_val_strc (arr, 1, nm_setting_connection_get_uuid (s_con));
set_val_strc (arr, 2, nm_setting_connection_get_connection_type (s_con));
@ -828,8 +839,9 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
NmcOutputField *arr;
const char *ac_path = NULL;
const char *ac_state = NULL;
char *ac_dev = NULL;
char *name, *ac_dev = NULL;
name = g_strdup_printf ("<invisible> %s", nm_active_connection_get_id (ac));
ac_path = nm_object_get_path (NM_OBJECT (ac));
ac_state = active_connection_state_to_string (nm_active_connection_get_state (ac));
ac_dev = get_ac_device_string (ac);
@ -837,7 +849,8 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
arr = nmc_dup_fields_array (nmc_fields_con_show,
sizeof (nmc_fields_con_show),
0);
set_val_strc (arr, 0, nm_active_connection_get_id (ac));
set_val_str (arr, 0, name);
set_val_strc (arr, 1, nm_active_connection_get_uuid (ac));
set_val_strc (arr, 2, nm_active_connection_get_connection_type (ac));
set_val_strc (arr, 3, NULL);
@ -851,6 +864,8 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, NmCli *nmc)
set_val_strc (arr, 11, ac_state);
set_val_strc (arr, 12, ac_path);
set_val_color_fmt_all (arr, NMC_TERM_FORMAT_DIM);
g_ptr_array_add (nmc->output_data, arr);
}
@ -927,36 +942,6 @@ fill_output_active_connection (NMActiveConnection *active,
g_string_free (dev_str, FALSE);
}
static void
fill_output_for_all_invisible (NmCli *nmc)
{
const GPtrArray *acons;
int a, c;
g_return_if_fail (nmc != NULL);
acons = nm_client_get_active_connections (nmc->client);
for (a = 0; a < acons->len; a++) {
gboolean found = FALSE;
NMActiveConnection *acon = g_ptr_array_index (acons, a);
const char *a_uuid = nm_active_connection_get_uuid (acon);
for (c = 0; c < nmc->connections->len; c++) {
NMConnection *con = g_ptr_array_index (nmc->connections, c);
const char *c_uuid = nm_connection_get_uuid (con);
if (strcmp (a_uuid, c_uuid) == 0) {
found = TRUE;
break;
}
}
/* Active connection is not in connections list */
if (!found)
fill_output_connection_for_invisible (acon, nmc);
}
}
typedef struct {
char **array;
guint32 idx;
@ -1340,12 +1325,174 @@ split_required_fields_for_con_show (const char *input,
return success;
}
typedef enum {
NMC_SORT_ACTIVE = 1,
NMC_SORT_ACTIVE_INV = -1,
NMC_SORT_NAME = 2,
NMC_SORT_NAME_INV = -2,
NMC_SORT_TYPE = 3,
NMC_SORT_TYPE_INV = -3,
NMC_SORT_PATH = 4,
NMC_SORT_PATH_INV = -4,
} NmcSortOrder;
typedef struct {
NmCli *nmc;
const GArray *order;
} NmcSortInfo;
static int
compare_connections (gconstpointer a, gconstpointer b, gpointer user_data)
{
NMConnection *ca = *(NMConnection **)a;
NMConnection *cb = *(NMConnection **)b;
NMActiveConnection *aca, *acb;
NmcSortInfo *info = (NmcSortInfo *) user_data;
GArray *default_order = NULL;
const GArray *order;
NmcSortOrder item;
int cmp = 0, i;
const char *tmp1, *tmp2;
unsigned long tmp1_int, tmp2_int;
if (info->order )
order = info->order;
else {
NmcSortOrder def[] = { NMC_SORT_ACTIVE, NMC_SORT_NAME, NMC_SORT_PATH };
int num = G_N_ELEMENTS (def);
default_order = g_array_sized_new (FALSE, FALSE, sizeof (NmcSortOrder), num);
g_array_append_vals (default_order, def, num);
order = default_order;
}
for (i = 0; i < order->len; i++) {
item = g_array_index (order, NmcSortOrder, i);
switch (item) {
case NMC_SORT_ACTIVE:
case NMC_SORT_ACTIVE_INV:
aca = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), ca);
acb = get_ac_for_connection (nm_client_get_active_connections (info->nmc->client), cb);
cmp = (aca && !acb) ? -1 : (!aca && acb) ? 1 : 0;
if (item == NMC_SORT_ACTIVE_INV)
cmp = -(cmp);
break;
case NMC_SORT_TYPE:
case NMC_SORT_TYPE_INV:
cmp = g_strcmp0 (nm_connection_get_connection_type (ca),
nm_connection_get_connection_type (cb));
if (item == NMC_SORT_TYPE_INV)
cmp = -(cmp);
break;
case NMC_SORT_NAME:
case NMC_SORT_NAME_INV:
cmp = g_strcmp0 (nm_connection_get_id (ca),
nm_connection_get_id (cb));
if (item == NMC_SORT_NAME_INV)
cmp = -(cmp);
break;
case NMC_SORT_PATH:
case NMC_SORT_PATH_INV:
tmp1 = nm_connection_get_path (ca);
tmp2 = nm_connection_get_path (cb);
tmp1 = tmp1 ? strrchr (tmp1, '/') : "0";
tmp2 = tmp2 ? strrchr (tmp2, '/') : "0";
nmc_string_to_uint (tmp1 ? tmp1+1 : "0", FALSE, 0, 0, &tmp1_int);
nmc_string_to_uint (tmp2 ? tmp2+1 : "0", FALSE, 0, 0, &tmp2_int);
cmp = (int) tmp1_int - tmp2_int;
if (item == NMC_SORT_PATH_INV)
cmp = -(cmp);
break;
default:
cmp = 0;
break;
}
if (cmp != 0)
goto end;
}
end:
if (default_order)
g_array_unref (default_order);
return cmp;
}
static GPtrArray *
sort_connections (const GPtrArray *cons, NmCli *nmc, const GArray *order)
{
GPtrArray *sorted;
int i;
NmcSortInfo compare_info;
compare_info.nmc = nmc;
compare_info.order = order;
sorted = g_ptr_array_sized_new (cons->len);
for (i = 0; cons && i < cons->len; i++)
g_ptr_array_add (sorted, cons->pdata[i]);
g_ptr_array_sort_with_data (sorted, compare_connections, &compare_info);
return sorted;
}
static int
compare_ac_connections (gconstpointer a, gconstpointer b, gpointer user_data)
{
NMActiveConnection *ca = *(NMActiveConnection **)a;
NMActiveConnection *cb = *(NMActiveConnection **)b;
int cmp;
/* Sort states first */
cmp = nm_active_connection_get_state (cb) - nm_active_connection_get_state (ca);
if (cmp != 0)
return cmp;
cmp = g_strcmp0 (nm_active_connection_get_id (ca),
nm_active_connection_get_id (cb));
if (cmp != 0)
return cmp;
return g_strcmp0 (nm_active_connection_get_connection_type (ca),
nm_active_connection_get_connection_type (cb));
}
static GPtrArray *
get_invisible_active_connections (NmCli *nmc)
{
const GPtrArray *acons;
GPtrArray *invisibles;
int a, c;
g_return_val_if_fail (nmc != NULL, NULL);
invisibles = g_ptr_array_new ();
acons = nm_client_get_active_connections (nmc->client);
for (a = 0; a < acons->len; a++) {
gboolean found = FALSE;
NMActiveConnection *acon = g_ptr_array_index (acons, a);
const char *a_uuid = nm_active_connection_get_uuid (acon);
for (c = 0; c < nmc->connections->len; c++) {
NMConnection *con = g_ptr_array_index (nmc->connections, c);
const char *c_uuid = nm_connection_get_uuid (con);
if (strcmp (a_uuid, c_uuid) == 0) {
found = TRUE;
break;
}
}
/* Active connection is not in connections array, add it to */
if (!found)
g_ptr_array_add (invisibles, acon);
}
g_ptr_array_sort_with_data (invisibles, compare_ac_connections, NULL);
return invisibles;
}
static NMCResultCode
do_connections_show (NmCli *nmc, gboolean active_only, gboolean show_secrets,
int argc, char **argv)
const GArray *order, int argc, char **argv)
{
GError *err = NULL;
char *profile_flds = NULL, *active_flds = NULL;
GPtrArray *invisibles, *sorted_cons;
nmc->should_wait = FALSE;
@ -1379,13 +1526,19 @@ do_connections_show (NmCli *nmc, gboolean active_only, gboolean show_secrets,
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);
/* Add values */
for (i = 0; i < nmc->connections->len; i++) {
NMConnection *con = NM_CONNECTION (nmc->connections->pdata[i]);
fill_output_connection (con, nmc, active_only);
}
/* Some active connections may not be in connection list, show them here. */
fill_output_for_all_invisible (nmc);
/* 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);
g_ptr_array_free (invisibles, FALSE);
/* Sort the connections and fill the output data */
sorted_cons = sort_connections (nmc->connections, nmc, order);
for (i = 0; i < sorted_cons->len; i++)
fill_output_connection (sorted_cons->pdata[i], nmc, active_only);
g_ptr_array_free (sorted_cons, FALSE);
print_data (nmc); /* Print all data */
} else {
gboolean new_line = FALSE;
@ -6190,11 +6343,8 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
{
char **match_array = NULL;
const char *line = rl_line_buffer;
const char *prompt = rl_prompt;
rl_compentry_func_t *generator_func = NULL;
gboolean copy_char;
const char *p1;
char *p2, *prompt_tmp;
char *prompt_tmp;
char *word = NULL;
size_t n1;
int num;
@ -6212,19 +6362,7 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
rl_complete_with_tilde_expansion = 1;
/* Filter out possible ANSI color escape sequences */
p1 = prompt;
p2 = prompt_tmp = g_strdup (prompt);
copy_char = TRUE;
while (*p1) {
if (*p1 == '\33')
copy_char = FALSE;
if (copy_char)
*p2++ = *p1;
if (!copy_char && *p1 == 'm')
copy_char = TRUE;
p1++;
}
*p2 = '\0';
prompt_tmp = nmc_filter_out_colors ((const char *) rl_prompt);
/* Find the first non-space character */
n1 = strspn (line, " \t");
@ -7020,7 +7158,8 @@ property_edit_submenu (NmCli *nmc,
gboolean temp_changes;
gboolean removed;
prompt = nmc_colorize (nmc->editor_prompt_color, "nmcli %s.%s> ",
prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s.%s> ",
nm_setting_get_name (curr_setting), prop_name);
while (cmd_property_loop) {
@ -7368,7 +7507,7 @@ menu_switch_to_level0 (NmcEditorMenuContext *menu_ctx,
{
menu_ctx->level = 0;
g_free (menu_ctx->main_prompt);
menu_ctx->main_prompt = nmc_colorize (prompt_color, "%s", prompt);
menu_ctx->main_prompt = nmc_colorize (prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
menu_ctx->curr_setting = NULL;
g_strfreev (menu_ctx->valid_props);
menu_ctx->valid_props = NULL;
@ -7384,7 +7523,8 @@ menu_switch_to_level1 (NmcEditorMenuContext *menu_ctx,
{
menu_ctx->level = 1;
g_free (menu_ctx->main_prompt);
menu_ctx->main_prompt = nmc_colorize (prompt_color, "nmcli %s> ", setting_name);
menu_ctx->main_prompt = nmc_colorize (prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ", setting_name);
menu_ctx->curr_setting = setting;
g_strfreev (menu_ctx->valid_props);
menu_ctx->valid_props = nmc_setting_get_valid_properties (menu_ctx->curr_setting);
@ -7418,7 +7558,8 @@ 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->editor_prompt_color, BASE_PROMPT);
menu_ctx.main_prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
menu_ctx.curr_setting = NULL;
menu_ctx.valid_props = NULL;
menu_ctx.valid_props_str = NULL;
@ -8054,9 +8195,11 @@ 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->editor_prompt_color, BASE_PROMPT);
menu_ctx.main_prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
else
menu_ctx.main_prompt = nmc_colorize (nmc->editor_prompt_color, "nmcli %s> ",
menu_ctx.main_prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ",
nm_setting_get_name (menu_ctx.curr_setting));
}
} else if (!cmd_arg_p) {
@ -8918,6 +9061,67 @@ nmcli_con_tab_completion (const char *text, int start, int end)
return match_array;
}
static GArray *
parse_preferred_connection_order (const char *order, GError **error)
{
char **strv, **iter;
const char *str;
GArray *order_arr;
NmcSortOrder val;
gboolean inverse;
int i;
strv = nmc_strsplit_set (order, ":", -1);
if (!strv || !*strv) {
g_set_error (error, NMCLI_ERROR, 0,
_("incorrect string '%s' of '--order' option"), order);
g_strfreev (strv);
return NULL;
}
order_arr = g_array_sized_new (FALSE, FALSE, sizeof (NmcSortOrder), 4);
for (iter = strv; iter && *iter; iter++) {
str = *iter;
inverse = FALSE;
if (str[0] == '-')
inverse = TRUE;
if (str[0] == '+' || str[0] == '-')
str++;
if (matches (str, "active") == 0)
val = inverse ? NMC_SORT_ACTIVE_INV : NMC_SORT_ACTIVE;
else if (matches (str, "name") == 0)
val = inverse ? NMC_SORT_NAME_INV : NMC_SORT_NAME;
else if (matches (str, "type") == 0)
val = inverse ? NMC_SORT_TYPE_INV : NMC_SORT_TYPE;
else if (matches (str, "path") == 0)
val = inverse ? NMC_SORT_PATH_INV : NMC_SORT_PATH;
else {
g_array_unref (order_arr);
order_arr = NULL;
g_set_error (error, NMCLI_ERROR, 0,
_("incorrect item '%s' in '--order' option"), *iter);
break;
}
/* Check duplicates*/
for (i = 0; i < order_arr->len; i++) {
if (abs (g_array_index (order_arr, NmcSortOrder, i)) - abs (val) == 0) {
g_array_unref (order_arr);
order_arr = NULL;
g_set_error (error, NMCLI_ERROR, 0,
_("'%s' repeats in '--order' option"), str);
goto end;
}
}
/* Value is ok and unique, add it to the array */
g_array_append_val (order_arr, val);
}
end:
g_strfreev (strv);
return order_arr;
}
/* Entry point function for connections-related commands: 'nmcli connection' */
NMCResultCode
do_connections (NmCli *nmc, int argc, char **argv)
@ -8960,16 +9164,17 @@ do_connections (NmCli *nmc, int argc, char **argv)
if (argc == 0) {
if (!nmc_terse_option_check (nmc->print_output, nmc->required_fields, &error))
goto opt_error;
nmc->return_value = do_connections_show (nmc, FALSE, FALSE, argc, argv);
nmc->return_value = do_connections_show (nmc, FALSE, FALSE, NULL, argc, argv);
} else {
if (matches (*argv, "show") == 0) {
gboolean active = FALSE;
gboolean show_secrets = FALSE;
GArray *order = NULL;
int i;
next_arg (&argc, &argv);
/* check connection show options [--active] [--show-secrets] */
for (i = 0; i < 2; i++) {
for (i = 0; i < 3; i++) {
if (!active && nmc_arg_is_option (*argv, "active")) {
active = TRUE;
next_arg (&argc, &argv);
@ -8978,8 +9183,21 @@ do_connections (NmCli *nmc, int argc, char **argv)
show_secrets = TRUE;
next_arg (&argc, &argv);
}
if (!order && nmc_arg_is_option (*argv, "order")) {
if (next_arg (&argc, &argv) != 0) {
g_set_error_literal (&error, NMCLI_ERROR, 0,
_("'--order' argument is missing"));
goto opt_error;
}
order = parse_preferred_connection_order (*argv, &error);
if (error)
goto opt_error;
next_arg (&argc, &argv);
}
}
nmc->return_value = do_connections_show (nmc, active, show_secrets, argc, argv);
nmc->return_value = do_connections_show (nmc, active, show_secrets, order, argc, argv);
if (order)
g_array_unref (order);
} else if (matches(*argv, "up") == 0) {
nmc->return_value = do_connection_up (nmc, argc-1, argv+1);
} else if (matches(*argv, "down") == 0) {

View file

@ -1188,15 +1188,27 @@ static void
fill_output_device_status (NMDevice *device, NmCli *nmc)
{
NMActiveConnection *ac;
NMDeviceState state;
NmcOutputField *arr = nmc_dup_fields_array (nmc_fields_dev_status,
sizeof (nmc_fields_dev_status),
0);
state = nm_device_get_state (device);
ac = nm_device_get_active_connection (device);
/* Show devices in color */
if (state <= NM_DEVICE_STATE_UNAVAILABLE)
set_val_color_fmt_all (arr, NMC_TERM_FORMAT_DIM);
else if (state == NM_DEVICE_STATE_DISCONNECTED)
set_val_color_all (arr, NMC_TERM_COLOR_RED);
else if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
set_val_color_all (arr, NMC_TERM_COLOR_YELLOW);
else if (state == NM_DEVICE_STATE_ACTIVATED)
set_val_color_all (arr, NMC_TERM_COLOR_GREEN);
set_val_strc (arr, 0, nm_device_get_iface (device));
set_val_strc (arr, 1, nm_device_get_type_description (device));
set_val_strc (arr, 2, nmc_device_state_to_string (nm_device_get_state (device)));
set_val_strc (arr, 2, nmc_device_state_to_string (state));
set_val_strc (arr, 3, nm_object_get_path (NM_OBJECT (device)));
set_val_strc (arr, 4, get_active_connection_id (device));
set_val_strc (arr, 5, ac ? nm_active_connection_get_uuid (ac) : NULL);

View file

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
#include "config.h"
@ -264,6 +264,26 @@ nm_state_to_string (NMState state)
}
}
static NmcTermColor
state_to_color (NMState state)
{
switch (state) {
case NM_STATE_CONNECTING:
return NMC_TERM_COLOR_YELLOW;
case NM_STATE_CONNECTED_LOCAL:
case NM_STATE_CONNECTED_SITE:
case NM_STATE_CONNECTED_GLOBAL:
return NMC_TERM_COLOR_GREEN;
case NM_STATE_DISCONNECTING:
return NMC_TERM_COLOR_YELLOW;
case NM_STATE_ASLEEP:
case NM_STATE_DISCONNECTED:
return NMC_TERM_COLOR_RED;
default:
return NMC_TERM_COLOR_NORMAL;
}
}
static const char *
nm_connectivity_to_string (NMConnectivityState connectivity)
{
@ -282,17 +302,33 @@ nm_connectivity_to_string (NMConnectivityState connectivity)
}
}
static NmcTermColor
connectivity_to_color (NMConnectivityState connectivity)
{
switch (connectivity) {
case NM_CONNECTIVITY_NONE:
return NMC_TERM_COLOR_RED;
case NM_CONNECTIVITY_PORTAL:
case NM_CONNECTIVITY_LIMITED:
return NMC_TERM_COLOR_YELLOW;
case NM_CONNECTIVITY_FULL:
return NMC_TERM_COLOR_GREEN;
default:
return NMC_TERM_COLOR_NORMAL;
}
}
static gboolean
show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_flds)
{
gboolean startup = FALSE;
NMState state = NM_STATE_UNKNOWN;
NMConnectivityState connectivity = NM_CONNECTIVITY_UNKNOWN;
const char *net_enabled_str;
const char *wireless_hw_enabled_str, *wireless_enabled_str;
const char *wwan_hw_enabled_str, *wwan_enabled_str;
gboolean net_enabled;
gboolean wireless_hw_enabled, wireless_enabled;
gboolean wwan_hw_enabled, wwan_enabled;
#if WITH_WIMAX
const char *wimax_hw_enabled_str, *wimax_enabled_str;
gboolean wimax_hw_enabled, wimax_enabled;
#endif
GError *error = NULL;
const char *fields_str;
@ -333,14 +369,14 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
state = nm_client_get_state (nmc->client);
startup = nm_client_get_startup (nmc->client);
connectivity = nm_client_get_connectivity (nmc->client);
net_enabled_str = nm_client_networking_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wireless_hw_enabled_str = nm_client_wireless_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wireless_enabled_str = nm_client_wireless_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wwan_hw_enabled_str = nm_client_wwan_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wwan_enabled_str = nm_client_wwan_get_enabled (nmc->client) ? _("enabled") : _("disabled");
net_enabled = nm_client_networking_get_enabled (nmc->client);
wireless_hw_enabled = nm_client_wireless_hardware_get_enabled (nmc->client);
wireless_enabled = nm_client_wireless_get_enabled (nmc->client);
wwan_hw_enabled = nm_client_wwan_hardware_get_enabled (nmc->client);
wwan_enabled = nm_client_wwan_get_enabled (nmc->client);
#if WITH_WIMAX
wimax_hw_enabled_str = nm_client_wimax_hardware_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wimax_enabled_str = nm_client_wimax_get_enabled (nmc->client) ? _("enabled") : _("disabled");
wimax_hw_enabled = nm_client_wimax_hardware_get_enabled (nmc->client);
wimax_enabled = nm_client_wimax_get_enabled (nmc->client);
#endif
nmc->print_fields.header_name = pretty_header_name ? (char *) pretty_header_name : _("NetworkManager status");
@ -353,15 +389,30 @@ show_nm_status (NmCli *nmc, const char *pretty_header_name, const char *print_fl
set_val_strc (arr, 2, nm_state_to_string (state));
set_val_strc (arr, 3, startup ? _("starting") : _("started"));
set_val_strc (arr, 4, nm_connectivity_to_string (connectivity));
set_val_strc (arr, 5, net_enabled_str);
set_val_strc (arr, 6, wireless_hw_enabled_str);
set_val_strc (arr, 7, wireless_enabled_str);
set_val_strc (arr, 8, wwan_hw_enabled_str);
set_val_strc (arr, 9, wwan_enabled_str);
set_val_strc (arr, 5, net_enabled ? _("enabled") : _("disabled"));
set_val_strc (arr, 6, wireless_hw_enabled ? _("enabled") : _("disabled"));
set_val_strc (arr, 7, wireless_enabled ? _("enabled") : _("disabled"));
set_val_strc (arr, 8, wwan_hw_enabled ? _("enabled") : _("disabled"));
set_val_strc (arr, 9, wwan_enabled ? _("enabled") : _("disabled"));
#if WITH_WIMAX
set_val_strc (arr, 10, wimax_hw_enabled_str);
set_val_strc (arr, 11, wimax_enabled_str);
set_val_strc (arr, 10, wimax_hw_enabled ? _("enabled") : _("disabled"));
set_val_strc (arr, 11, wimax_enabled ? _("enabled") : _("disabled"));
#endif
/* Set colors */
arr[2].color = state_to_color (state);
arr[3].color = startup ? NMC_TERM_COLOR_YELLOW : NMC_TERM_COLOR_GREEN;
arr[4].color = connectivity_to_color (connectivity);
arr[5].color = net_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
arr[6].color = wireless_hw_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
arr[7].color = wireless_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
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;
#if WITH_WIMAX
arr[10].color = wimax_hw_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
arr[11].color = wimax_enabled ? NMC_TERM_COLOR_GREEN : NMC_TERM_COLOR_RED;
#endif
g_ptr_array_add (nmc->output_data, arr);
print_data (nmc); /* Print all data */

View file

@ -16,7 +16,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
/* Generated configuration file */
@ -89,6 +89,7 @@ usage (const char *prog_name)
" -t[erse] terse output\n"
" -p[retty] pretty output\n"
" -m[ode] tabular|multiline output mode\n"
" -c[olors] auto|yes|no whether to use colors in output\n"
" -f[ields] <field1,field2,...>|all|common specify fields to output\n"
" -e[scape] yes|no escape columns separators in values\n"
" -n[ocheck] don't check nmcli and NetworkManager versions\n"
@ -210,6 +211,24 @@ parse_command_line (NmCli *nmc, int argc, char **argv)
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return nmc->return_value;
}
} else if (matches (opt, "-colors") == 0) {
next_arg (&argc, &argv);
if (argc <= 1) {
g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return nmc->return_value;
}
if (matches (argv[1], "auto") == 0)
nmc->use_colors = NMC_USE_COLOR_AUTO;
else if (matches (argv[1], "yes") == 0)
nmc->use_colors = NMC_USE_COLOR_YES;
else if (matches (argv[1], "no") == 0)
nmc->use_colors = NMC_USE_COLOR_NO;
else {
g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[1], opt);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
return nmc->return_value;
}
} else if (matches (opt, "-escape") == 0) {
next_arg (&argc, &argv);
if (argc <= 1) {
@ -526,6 +545,7 @@ nmc_init (NmCli *nmc)
memset (&nmc->print_fields, '\0', sizeof (NmcPrintFields));
nmc->nocheck_ver = FALSE;
nmc->ask = FALSE;
nmc->use_colors = NMC_USE_COLOR_AUTO;
nmc->in_editor = FALSE;
nmc->editor_status_line = FALSE;
nmc->editor_save_confirmation = TRUE;

View file

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
#ifndef NMC_NMCLI_H
@ -68,6 +68,28 @@ typedef enum {
NMC_RESULT_ERROR_NOT_FOUND = 10
} NMCResultCode;
typedef enum {
NMC_TERM_COLOR_NORMAL = 0,
NMC_TERM_COLOR_BLACK = 1,
NMC_TERM_COLOR_RED = 2,
NMC_TERM_COLOR_GREEN = 3,
NMC_TERM_COLOR_YELLOW = 4,
NMC_TERM_COLOR_BLUE = 5,
NMC_TERM_COLOR_MAGENTA = 6,
NMC_TERM_COLOR_CYAN = 7,
NMC_TERM_COLOR_WHITE = 8
} NmcTermColor;
typedef enum {
NMC_TERM_FORMAT_NORMAL,
NMC_TERM_FORMAT_BOLD,
NMC_TERM_FORMAT_DIM,
NMC_TERM_FORMAT_UNDERLINE,
NMC_TERM_FORMAT_BLINK,
NMC_TERM_FORMAT_REVERSE,
NMC_TERM_FORMAT_HIDDEN,
} NmcTermFormat;
typedef enum {
NMC_PRINT_TERSE = 0,
NMC_PRINT_NORMAL = 1,
@ -90,6 +112,8 @@ typedef struct _NmcOutputField {
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 */
} NmcOutputField;
typedef struct {
@ -99,16 +123,10 @@ typedef struct {
} NmcPrintFields;
typedef enum {
NMC_TERM_COLOR_NORMAL = 0,
NMC_TERM_COLOR_BLACK = 1,
NMC_TERM_COLOR_RED = 2,
NMC_TERM_COLOR_GREEN = 3,
NMC_TERM_COLOR_YELLOW = 4,
NMC_TERM_COLOR_BLUE = 5,
NMC_TERM_COLOR_MAGENTA = 6,
NMC_TERM_COLOR_CYAN = 7,
NMC_TERM_COLOR_WHITE = 8
} NmcTermColor;
NMC_USE_COLOR_AUTO,
NMC_USE_COLOR_YES,
NMC_USE_COLOR_NO,
} NmcColorOption;
/* NmCli - main structure */
typedef struct _NmCli {
@ -131,6 +149,7 @@ typedef struct _NmCli {
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 */
char *required_fields; /* Required fields in output: '--fields' option */
GPtrArray *output_data; /* GPtrArray of arrays of NmcOutputField structs - accumulates data for output */

View file

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
/* Generated configuration file */
@ -307,28 +307,121 @@ nmc_term_color_sequence (NmcTermColor color)
}
}
const char *
nmc_term_format_sequence (NmcTermFormat format)
{
switch (format) {
case NMC_TERM_FORMAT_BOLD:
return "\33[1m";
break;
case NMC_TERM_FORMAT_DIM:
return "\33[2m";
break;
case NMC_TERM_FORMAT_UNDERLINE:
return "\33[4m";
break;
case NMC_TERM_FORMAT_BLINK:
return "\33[5m";
break;
case NMC_TERM_FORMAT_REVERSE:
return "\33[7m";
break;
case NMC_TERM_FORMAT_HIDDEN:
return "\33[8m";
break;
default:
return "";
break;
}
}
char *
nmc_colorize (NmcTermColor color, const char *fmt, ...)
nmc_colorize (NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
{
va_list args;
char *str, *colored;
const char *ansi_color, *color_end;
const char *ansi_color, *color_end, *ansi_fmt, *format_end;
static const char *end_seq = "\33[0m";
va_start (args, fmt);
str = g_strdup_vprintf (fmt, args);
va_end (args);
ansi_color = nmc_term_color_sequence (color);
if (*ansi_color)
color_end = "\33[0m";
else
color_end = "";
ansi_fmt = nmc_term_format_sequence (format);
color_end = *ansi_color ? end_seq : "";
format_end = *ansi_fmt ? end_seq : "";
colored = g_strdup_printf ("%s%s%s", ansi_color, str, color_end);
colored = g_strdup_printf ("%s%s%s%s%s", ansi_fmt, ansi_color, str, color_end, format_end);
g_free (str);
return colored;
}
/*
* Count characters belonging to terminal color escape sequences.
* @start points to beginning of the string, @end points to the end,
* or NULL if the string is nul-terminated.
*/
static int
nmc_count_color_escape_chars (const char *start, const char *end)
{
int num = 0;
gboolean inside = FALSE;
if (end == NULL)
end = start + strlen (start);
while (start < end) {
if (*start == '\33' && *(start+1) == '[')
inside = TRUE;
if (inside)
num++;
if (*start == 'm')
inside = FALSE;
start++;
}
return num;
}
/* Filter out possible ANSI color escape sequences */
/* It directly modifies the passed string @str. */
void
nmc_filter_out_colors_inplace (char *str)
{
const char *p1;
char *p2;
gboolean copy_char = TRUE;
if (!str)
return;
p1 = p2 = str;
while (*p1) {
if (*p1 == '\33' && *(p1+1) == '[')
copy_char = FALSE;
if (copy_char)
*p2++ = *p1;
if (!copy_char && *p1 == 'm')
copy_char = TRUE;
p1++;
}
*p2 = '\0';
}
/* Filter out possible ANSI color escape sequences */
char *
nmc_filter_out_colors (const char *str)
{
char *filtered;
if (!str)
return NULL;
filtered = g_strdup (str);
nmc_filter_out_colors_inplace (filtered);
return filtered;
}
/*
* Convert string to signed integer.
* If required, the resulting number is checked to be in the <min,max> range.
@ -588,21 +681,24 @@ nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens)
}
/*
* Find out how many columns an UTF-8 string occupies on the screen
* Find out how many columns an UTF-8 string occupies on the screen.
*/
int
nmc_string_screen_width (const char *start, const char *end)
{
int width = 0;
const char *p = start;
if (end == NULL)
end = start + strlen (start);
while (start < end) {
width += g_unichar_iswide (g_utf8_get_char (start)) ? 2 : g_unichar_iszerowidth (g_utf8_get_char (start)) ? 0 : 1;
start = g_utf8_next_char (start);
while (p < end) {
width += g_unichar_iswide (g_utf8_get_char (p)) ? 2 : g_unichar_iszerowidth (g_utf8_get_char (p)) ? 0 : 1;
p = g_utf8_next_char (p);
}
return width;
/* Subtract color escape sequences as they don't occupy space. */
return width - nmc_count_color_escape_chars (start, NULL);
}
void
@ -637,6 +733,26 @@ set_val_arrc (NmcOutputField fields_array[], guint32 idx, const char **value)
fields_array[idx].free_value = FALSE;
}
void
set_val_color_all (NmcOutputField fields_array[], NmcTermColor color)
{
int i;
for (i = 0; fields_array[i].name; i++) {
fields_array[i].color = color;
}
}
void
set_val_color_fmt_all (NmcOutputField fields_array[], NmcTermFormat format)
{
int i;
for (i = 0; fields_array[i].name; i++) {
fields_array[i].color_fmt = format;
}
}
/*
* Free 'value' members in array of NmcOutputField
*/
@ -855,23 +971,55 @@ nmc_empty_output_fields (NmCli *nmc)
}
static char *
get_value_to_print (NmcOutputField *fields,
colorize_string (gboolean colorize,
NmcTermColor color,
NmcTermFormat color_fmt,
const char *str,
gboolean *dealloc)
{
char *out;
if ( colorize
&& (color != NMC_TERM_COLOR_NORMAL || color_fmt != NMC_TERM_FORMAT_NORMAL)) {
out = nmc_colorize (color, color_fmt, str);
*dealloc = TRUE;
} else {
out = (char *) str;
*dealloc = FALSE;
}
return out;
}
static char *
get_value_to_print (NmcOutputField *field,
gboolean field_name,
const char *not_set_str,
gboolean *dealloc)
gboolean *dealloc,
gboolean colorize)
{
gboolean is_array = fields->value_is_array;
char *value;
gboolean is_array = field->value_is_array;
char *value, *out;
gboolean free_value, free_out;
if (field_name)
value = _(fields->name_l10n);
value = _(field->name_l10n);
else
value = fields->value ?
(is_array ? g_strjoinv (" | ", (char **) fields->value) :
(char *) fields->value) :
value = field->value ?
(is_array ? g_strjoinv (" | ", (char **) field->value) :
(char *) field->value) :
(char *) not_set_str;
*dealloc = fields->value && is_array && !field_name;
return value;
free_value = field->value && is_array && !field_name;
/* colorize the value */
out = colorize_string (colorize, field->color, field->color_fmt, value, &free_out);
if (free_out) {
if (free_value)
g_free (value);
*dealloc = TRUE;
} else
*dealloc = free_value;
return out;
}
/*
@ -901,6 +1049,7 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
gboolean field_names = field_values[0].flags & NMC_OF_FLAG_FIELD_NAMES;
gboolean section_prefix = field_values[0].flags & NMC_OF_FLAG_SECTION_PREFIX;
gboolean main_header = main_header_add || main_header_only;
gboolean colorize;
/* No headers are printed in terse mode:
* - neither main header nor field (column) names
@ -908,6 +1057,11 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
if ((main_header_only || field_names) && terse)
return;
/* Only show colors if the output is a terminal */
colorize = nmc->use_colors == NMC_USE_COLOR_YES ? TRUE :
nmc->use_colors == NMC_USE_COLOR_NO ? FALSE :
isatty (fileno (stdout));
if (multiline) {
/* --- Multiline mode --- */
enum { ML_HEADER_WIDTH = 79 };
@ -930,6 +1084,7 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
if (!main_header_only && !field_names) {
for (i = 0; i < fields.indices->len; i++) {
char *tmp;
gboolean free_print_val;
int idx = g_array_index (fields.indices, int, i);
gboolean is_array = field_values[idx].value_is_array;
@ -941,10 +1096,14 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
if (is_array) {
/* value is a null-terminated string array */
const char **p;
const char **p, *val;
char *print_val;
int j;
for (p = (const char **) field_values[idx].value, j = 1; p && *p; p++, j++) {
val = *p ? *p : not_set_str;
print_val = colorize_string (colorize, field_values[idx].color, field_values[idx].color_fmt,
val, &free_print_val);
tmp = g_strdup_printf ("%s%s%s[%d]:",
section_prefix ? (const char*) field_values[0].value : "",
section_prefix ? "." : "",
@ -952,24 +1111,30 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
j);
width1 = strlen (tmp);
width2 = nmc_string_screen_width (tmp, NULL);
g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp,
*p ? *p : not_set_str);
g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, print_val);
g_free (tmp);
if (free_print_val)
g_free (print_val);
}
} else {
/* value is a string */
const char *hdr_name = (const char*) field_values[0].value;
const char *val = (const char*) field_values[idx].value;
char *print_val;
val = val ? val : not_set_str;
print_val = colorize_string (colorize, field_values[idx].color, field_values[idx].color_fmt,
val, &free_print_val);
tmp = g_strdup_printf ("%s%s%s:",
section_prefix ? hdr_name : "",
section_prefix ? "." : "",
_(field_values[idx].name_l10n));
width1 = strlen (tmp);
width2 = nmc_string_screen_width (tmp, NULL);
g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp,
val ? val : not_set_str);
g_print ("%-*s%s\n", terse ? 0 : ML_VALUE_INDENT+width1-width2, tmp, print_val);
g_free (tmp);
if (free_print_val)
g_free (print_val);
}
}
if (pretty) {
@ -987,7 +1152,8 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
for (i = 0; i < fields.indices->len; i++) {
int idx = g_array_index (fields.indices, int, i);
gboolean dealloc;
char *value = get_value_to_print ((NmcOutputField *) field_values+idx, field_names, not_set_str, &dealloc);
char *value = get_value_to_print ((NmcOutputField *) field_values+idx, field_names,
not_set_str, &dealloc, colorize);
if (terse) {
if (escape) {
@ -1085,7 +1251,7 @@ print_data (NmCli *nmc)
char *value;
row = g_ptr_array_index (nmc->output_data, j);
field_names = row[0].flags & NMC_OF_FLAG_FIELD_NAMES;
value = get_value_to_print (row+i, field_names, "--", &dealloc);
value = get_value_to_print (row+i, field_names, "--", &dealloc, FALSE);
len = nmc_string_screen_width (value, NULL);
max_width = len > max_width ? len : max_width;
if (dealloc)

View file

@ -14,7 +14,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2010 - 2014 Red Hat, Inc.
* Copyright 2010 - 2015 Red Hat, Inc.
*/
#ifndef NMC_UTILS_H
@ -67,7 +67,10 @@ char *nmc_ip6_address_as_string (const struct in6_addr *ip, GError **error);
void nmc_terminal_erase_line (void);
void nmc_terminal_show_progress (const char *str);
const char *nmc_term_color_sequence (NmcTermColor color);
char *nmc_colorize (NmcTermColor color, const char * fmt, ...);
const char *nmc_term_format_sequence (NmcTermFormat format);
char *nmc_colorize (NmcTermColor color, NmcTermFormat format, const char * fmt, ...);
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, char ***argv, int *argc);
const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error);
@ -79,6 +82,8 @@ void set_val_str (NmcOutputField fields_array[], guint32 index, char *value);
void set_val_strc (NmcOutputField fields_array[], guint32 index, const char *value);
void set_val_arr (NmcOutputField fields_array[], guint32 index, char **value);
void set_val_arrc (NmcOutputField fields_array[], guint32 index, const char **value);
void set_val_color_all (NmcOutputField fields_array[], NmcTermColor color);
void set_val_color_fmt_all (NmcOutputField fields_array[], NmcTermFormat format);
void nmc_free_output_field_values (NmcOutputField fields_array[]);
GArray *parse_output_fields (const char *fields_str,
const NmcOutputField fields_array[],

View file

@ -19,9 +19,9 @@
.\" with this manual; if not, write to the Free Software Foundation, Inc.,
.\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
.\"
.\" Copyright 2010 - 2014 Red Hat, Inc.
.\" Copyright 2010 - 2015 Red Hat, Inc.
.\"
.TH NMCLI "1" "3 December 2014"
.TH NMCLI "1" "19 February 2015"
.SH NAME
nmcli \- command\(hyline tool for controlling NetworkManager
@ -45,6 +45,8 @@ nmcli \- command\(hyline tool for controlling NetworkManager
.br
\fB\-m\fR[\fImode\fR] tabular | multiline
.br
\fB\-c\fR[\fIcolors\fR] auto | yes | no
.br
\fB\-f\fR[\fIields\fR] <field1,field2,...> | all | common
.br
\fB\-e\fR[\fIscape\fR] yes | no
@ -106,6 +108,11 @@ Columns define particular properties of the entry.
\fImultiline\fP \(en Each entry comprises multiple lines, each property on its own
line. The values are prefixed with the property name.
.TP
.B \-c, \-\-colors auto|yes|no
This option controls color output (using terminal escape sequences). \fIyes\fP
enables colors, \fIno\fP disables them, \fIauto\fP only produces colors when
standard output is directed to a terminal. The default value is \fIauto\fP.
.TP
.B \-f, \-\-fields <field1,field2,...> | all | common
This option is used to specify what fields (column names) should be printed.
Valid field names differ for specific commands. List available fields by
@ -289,12 +296,31 @@ active if a device is using that connection profile. Without a parameter, all
profiles are listed. When --active option is specified, only the active profiles
are shown.
.TP
.B show [--active] [--show-secrets] [ id | uuid | path | apath ] <ID> ...
.B show [--active] [--order <order spec>] [--show-secrets] [ id | uuid | path | apath ] <ID> ...
.br
Show details for specified connections. By default, both static configuration
and active connection data are displayed. When --active option is specified,
only the active profiles are taken into account. When --show-secrets option is
specified, secrets associated with the profile will be revealed too.
.sp
Ordering:
.br
The --order option can be used to get custom ordering of connections. The
connections can be ordered by active status, name, type or D-Bus path. If
connections are equal according to a sort order category, an additional
category can be specified.
The default sorting order is equivalent to "--order active:name:path".
.sp
<order spec> := category:category:...
.br
categogy := [+-]active | [+-]name | [+-]type | [+-]path
.br
\fI+\fP or no prefix means sorting in ascending order (alphabetically or in numbers).
.br
\fI-\fP means reverse (descending) order.
.br
The category names can be abbreviated (e.g. --order -a:na)
.sp
\fIid\fP, \fIuuid\fP, \fIpath\fP and \fIapath\fP keywords can be used if
\fI<ID>\fP is ambiguous.
.RS