cli: changing nmcli output to better fit both computer and human needs

The output is basically tabular with fields (columns) presenting specific pieces of info.
Each line represents a single object. It's possible to switch to multiline output using
'--multiline' option. In that mode single object is presented on more lines - each field
on its line.
Terse mode now uses ':' as field separator. It also escapes all occurences of ':' and '\'
inside field values to ease parsing. The escaping behaviour can be controlled through
'--escape' option. By default, escaping is switched on in tabular mode. When using terse
mode ('--terse'), '--fields' option is mandatory for specifying required fields. That helps
for flexibility and backwards compatibility.
Not all output is converted yet.
This commit is contained in:
Jiří Klimeš 2010-03-18 15:39:15 +01:00
parent 15351042ba
commit 55949277bd
6 changed files with 727 additions and 283 deletions

View file

@ -53,6 +53,37 @@
#include "connections.h"
/* Available field for 'con status' */
static NmcOutputField nmc_fields_con_status[] = {
{"NAME", N_("NAME"), 25, NULL, 0}, /* 0 */
{"UUID", N_("UUID"), 38, NULL, 0}, /* 1 */
{"DEVICES", N_("DEVICES"), 10, NULL, 0}, /* 2 */
{"SCOPE", N_("SCOPE"), 8, NULL, 0}, /* 3 */
{"DEFAULT", N_("DEFAULT"), 8, NULL, 0}, /* 4 */
{"DBUS-SERVICE", N_("DBUS-SERVICE"), 45, NULL, 0}, /* 5 */
{"SPEC-OBJECT", N_("SPEC-OBJECT"), 10, NULL, 0}, /* 6 */
{"VPN", N_("VPN"), 5, NULL, 0}, /* 7 */
{NULL, NULL, 0, NULL, 0}
};
#define NMC_FIELDS_CON_STATUS_ALL "NAME,UUID,DEVICES,SCOPE,DEFAULT,VPN,DBUS-SERVICE,SPEC-OBJECT"
#define NMC_FIELDS_CON_STATUS_COMMON "NAME,UUID,DEVICES,SCOPE,DEFAULT,VPN"
/* Available field for 'con list' */
static NmcOutputField nmc_fields_con_list[] = {
{"NAME", N_("NAME"), 25, NULL, 0}, /* 0 */
{"UUID", N_("UUID"), 38, NULL, 0}, /* 1 */
{"TYPE", N_("TYPE"), 17, NULL, 0}, /* 2 */
{"SCOPE", N_("SCOPE"), 8, NULL, 0}, /* 3 */
{"TIMESTAMP", N_("TIMESTAMP"), 12, NULL, 0}, /* 4 */
{"TIMESTAMP-REAL", N_("TIMESTAMP-REAL"), 34, NULL, 0}, /* 5 */
{"AUTOCONNECT", N_("AUTOCONNECT"), 13, NULL, 0}, /* 6 */
{"READONLY", N_("READONLY"), 10, NULL, 0}, /* 7 */
{NULL, NULL, 0, NULL, 0}
};
#define NMC_FIELDS_CON_LIST_ALL "NAME,UUID,TYPE,SCOPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,READONLY"
#define NMC_FIELDS_CON_LIST_COMMON "NAME,UUID,TYPE,SCOPE,TIMESTAMP-REAL"
typedef struct {
NmCli *nmc;
int argc;
@ -102,17 +133,31 @@ static void
show_connection (NMConnection *data, gpointer user_data)
{
NMConnection *connection = (NMConnection *) data;
NmCli *nmc = (NmCli *) user_data;
NMSettingConnection *s_con;
const char *id;
const char *uuid;
const char *con_type;
guint64 timestamp;
char *timestamp_str;
char timestamp_real_str[64];
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
if (s_con) {
id = nm_setting_connection_get_id (s_con);
uuid = nm_setting_connection_get_uuid (s_con);
con_type = nm_setting_connection_get_connection_type (s_con);
print_table_line (0, con_type, 17, uuid, 38, id, 0, NULL);
/* Obtain field values */
timestamp = nm_setting_connection_get_timestamp (s_con);
timestamp_str = g_strdup_printf ("%ld", timestamp);
strftime (timestamp_real_str, sizeof (timestamp_real_str), "%c", localtime ((time_t *) &timestamp));
nmc->allowed_fields[0].value = nm_setting_connection_get_id (s_con);
nmc->allowed_fields[1].value = nm_setting_connection_get_uuid (s_con);
nmc->allowed_fields[2].value = nm_setting_connection_get_connection_type (s_con);
nmc->allowed_fields[3].value = nm_connection_get_scope (connection) == NM_CONNECTION_SCOPE_SYSTEM ? _("system") : _("user");
nmc->allowed_fields[4].value = timestamp_str;
nmc->allowed_fields[5].value = timestamp ? timestamp_real_str : _("never");
nmc->allowed_fields[6].value = nm_setting_connection_get_autoconnect (s_con) ? _("yes") : _("no");
nmc->allowed_fields[7].value = nm_setting_connection_get_read_only (s_con) ? _("yes") : _("no");
nmc->print_fields.flags &= ~NMC_PF_FLAG_HEADER; /* Clear HEADER flag */
print_fields (nmc->print_fields, nmc->allowed_fields);
g_free (timestamp_str);
}
}
@ -148,24 +193,46 @@ find_connection (GSList *list, const char *filter_type, const char *filter_val)
static NMCResultCode
do_connections_list (NmCli *nmc, int argc, char **argv)
{
GError *error = NULL;
char *fields_str;
char *fields_all = NMC_FIELDS_CON_LIST_ALL;
char *fields_common = NMC_FIELDS_CON_LIST_COMMON;
guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
gboolean valid_param_specified = FALSE;
nmc->should_wait = FALSE;
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
fields_str = fields_all;
else
fields_str = nmc->required_fields;
nmc->allowed_fields = nmc_fields_con_list;
nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error);
if (error) {
g_string_printf (nmc->return_text, error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
if (argc == 0) {
valid_param_specified = TRUE;
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("Connections"), _("Type"), 17, _("UUID"), 38, _("Name"), 20, NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("Type"), 17, _("UUID"), 38, _("Name"), 0, NULL);
if (nmc->print_output > NMC_PRINT_TERSE)
printf (_("System connections:\n"));
g_slist_foreach (nmc->system_connections, (GFunc) show_connection, NULL);
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("System connections");
print_fields (nmc->print_fields, nmc->allowed_fields);
g_slist_foreach (nmc->system_connections, (GFunc) show_connection, nmc);
if (nmc->print_output > NMC_PRINT_TERSE)
printf (_("User connections:\n"));
g_slist_foreach (nmc->user_connections, (GFunc) show_connection, NULL);
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("User connections");
print_fields (nmc->print_fields, nmc->allowed_fields);
g_slist_foreach (nmc->user_connections, (GFunc) show_connection, nmc);
}
else {
while (argc > 0) {
@ -189,24 +256,25 @@ do_connections_list (NmCli *nmc, int argc, char **argv)
g_string_printf (nmc->return_text, _("Error: %s - no such connection."), *argv);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
}
break;
}
else if (strcmp (*argv, "system") == 0) {
valid_param_specified = TRUE;
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("System-wide connections"), _("Type"), 17, _("UUID"), 38, _("Name"), 20, NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("Type"), 17, _("UUID"), 38, _("Name"), 0, NULL);
g_slist_foreach (nmc->system_connections, (GFunc) show_connection, NULL);
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("System connections");
print_fields (nmc->print_fields, nmc->allowed_fields);
g_slist_foreach (nmc->system_connections, (GFunc) show_connection, nmc);
break;
}
else if (strcmp (*argv, "user") == 0) {
valid_param_specified = TRUE;
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("User connections"), _("Type"), 17, _("UUID"), 38, _("Name"), 20, NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("Type"), 17, _("UUID"), 38, _("Name"), 0, NULL);
g_slist_foreach (nmc->user_connections, (GFunc) show_connection, NULL);
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("User connections");
print_fields (nmc->print_fields, nmc->allowed_fields);
g_slist_foreach (nmc->user_connections, (GFunc) show_connection, nmc);
break;
}
else {
fprintf (stderr, _("Unknown parameter: %s\n"), *argv);
@ -226,12 +294,17 @@ error:
return nmc->return_value;
}
typedef struct {
NmCli *nmc;
NMConnectionScope scope;
} StatusInfo;
static void
show_active_connection (gpointer data, gpointer user_data)
{
NMActiveConnection *active = NM_ACTIVE_CONNECTION (data);
GSList *con_list = (GSList *) user_data;
GSList *iter;
StatusInfo *info = (StatusInfo *) user_data;
GSList *con_list, *iter;
const char *active_path;
NMConnectionScope active_service_scope;
NMSettingConnection *s_con;
@ -239,12 +312,14 @@ show_active_connection (gpointer data, gpointer user_data)
GString *dev_str;
int i;
dev_str = g_string_new (NULL);
active_path = nm_active_connection_get_connection (active);
active_service_scope = nm_active_connection_get_scope (active);
if (active_service_scope != info->scope)
return;
/* Get devices of the active connection */
dev_str = g_string_new (NULL);
devices = nm_active_connection_get_devices (active);
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *device = g_ptr_array_index (devices, i);
@ -255,24 +330,29 @@ show_active_connection (gpointer data, gpointer user_data)
if (dev_str->len > 0)
g_string_truncate (dev_str, dev_str->len - 1); /* Cut off last ',' */
con_list = (info->scope == NM_CONNECTION_SCOPE_SYSTEM) ? info->nmc->system_connections : info->nmc->user_connections;
for (iter = con_list; iter; iter = g_slist_next (iter)) {
NMConnection *connection = (NMConnection *) iter->data;
const char *con_path = nm_connection_get_path (connection);
NMConnectionScope con_scope = nm_connection_get_scope (connection);
if (!strcmp (active_path, con_path) && active_service_scope == con_scope) {
/* this connection is active */
if (!strcmp (active_path, con_path)) {
/* This connection is active */
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
g_assert (s_con != NULL);
// FIXME: Fix the output
print_table_line (0, nm_active_connection_get_default (active) ? _("yes") : _("no"), 8,
nm_active_connection_get_service_name (active), 45,
// nm_active_connection_get_specific_object (active), 0,
// nm_active_connection_get_connection (active), 0,
dev_str->str, 10,
nm_setting_connection_get_uuid (s_con), 38,
nm_setting_connection_get_id (s_con), 0, NULL);
/* Obtain field values */
info->nmc->allowed_fields[0].value = nm_setting_connection_get_id (s_con);
info->nmc->allowed_fields[1].value = nm_setting_connection_get_uuid (s_con);
info->nmc->allowed_fields[2].value = dev_str->str;
info->nmc->allowed_fields[3].value = active_service_scope == NM_CONNECTION_SCOPE_SYSTEM ? _("system") : _("user");
info->nmc->allowed_fields[4].value = nm_active_connection_get_default (active) ? _("yes") : _("no");
info->nmc->allowed_fields[5].value = nm_active_connection_get_service_name (active);
info->nmc->allowed_fields[6].value = nm_active_connection_get_specific_object (active);
info->nmc->allowed_fields[7].value = NM_IS_VPN_CONNECTION (active) ? _("yes") : _("no");
info->nmc->print_fields.flags &= ~NMC_PF_FLAG_HEADER; /* Clear HEADER flag */
print_fields (info->nmc->print_fields, info->nmc->allowed_fields);
break;
}
}
@ -283,6 +363,14 @@ static NMCResultCode
do_connections_status (NmCli *nmc, int argc, char **argv)
{
const GPtrArray *active_cons;
GError *error = NULL;
StatusInfo *info;
char *fields_str;
char *fields_all = NMC_FIELDS_CON_STATUS_ALL;
char *fields_common = NMC_FIELDS_CON_STATUS_COMMON;
guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
nmc->should_wait = FALSE;
@ -292,18 +380,40 @@ do_connections_status (NmCli *nmc, int argc, char **argv)
active_cons = nm_client_get_active_connections (nmc->client);
// FIXME: Fix the output
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("Active connections"), _("Default"), 8, _("Service"), 45, _("Devices"), 10, _("UUID"), 38, _("Name"), 20, NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("Default"), 8, _("Service"), 45, _("Devices"), 10, _("UUID"), 38, _("Name"), 0, NULL);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
fields_str = fields_all;
else
fields_str = nmc->required_fields;
if (active_cons && active_cons->len) {
g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) nmc->system_connections);
g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) nmc->user_connections);
nmc->allowed_fields = nmc_fields_con_status;
nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error);
if (error) {
g_string_printf (nmc->return_text, error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
return NMC_RESULT_SUCCESS;
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("Active connections");
print_fields (nmc->print_fields, nmc->allowed_fields);
if (active_cons && active_cons->len) {
info = g_malloc0 (sizeof (StatusInfo));
info->nmc = nmc;
info->scope = NM_CONNECTION_SCOPE_SYSTEM;
g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) info);
info->scope = NM_CONNECTION_SCOPE_USER;
g_ptr_array_foreach ((GPtrArray *) active_cons, show_active_connection, (gpointer) info);
g_free (info);
}
error:
return nmc->return_value;
}
/* --------------------

View file

@ -55,6 +55,35 @@
#include "devices.h"
/* Available field for 'dev status' */
static NmcOutputField nmc_fields_dev_status[] = {
{"DEVICE", N_("DEVICE"), 10, NULL, 0}, /* 0 */
{"TYPE", N_("TYPE"), 17, NULL, 0}, /* 1 */
{"STATE", N_("STATE"), 12, NULL, 0}, /* 2 */
{NULL, NULL, 0, NULL, 0}
};
#define NMC_FIELDS_DEV_STATUS_ALL "DEVICE,TYPE,STATE"
#define NMC_FIELDS_DEV_STATUS_COMMON "DEVICE,TYPE,STATE"
/* Available field for 'dev wifi list' */
static NmcOutputField nmc_fields_dev_wifi_list[] = {
{"SSID", N_("SSID"), 33, NULL, 0}, /* 0 */
{"BSSID", N_("BSSID"), 19, NULL, 0}, /* 1 */
{"MODE", N_("MODE"), 16, NULL, 0}, /* 2 */
{"FREQ", N_("FREQ"), 10, NULL, 0}, /* 3 */
{"RATE", N_("RATE"), 10, NULL, 0}, /* 4 */
{"SIGNAL", N_("SIGNAL"), 8, NULL, 0}, /* 5 */
{"SECURITY", N_("SECURITY"), 10, NULL, 0}, /* 6 */
{"WPA-FLAGS", N_("WPA-FLAGS"), 25, NULL, 0}, /* 7 */
{"RSN-FLAGS", N_("RSN-FLAGS"), 25, NULL, 0}, /* 8 */
{"DEVICE", N_("DEVICE"), 10, NULL, 0}, /* 9 */
{"ACTIVE", N_("ACTIVE"), 8, NULL, 0}, /* 10 */
{NULL, NULL, 0, NULL, 0}
};
#define NMC_FIELDS_DEV_WIFI_LIST_ALL "SSID,BSSID,MODE,FREQ,RATE,SIGNAL,SECURITY,WPA-FLAGS,RSN-FLAGS,DEVICE,ACTIVE"
#define NMC_FIELDS_DEV_WIFI_LIST_COMMON "SSID,BSSID,MODE,FREQ,RATE,SIGNAL,SECURITY,ACTIVE"
/* static function prototypes */
static void usage (void);
static const char *device_state_to_string (NMDeviceState state);
@ -75,7 +104,7 @@ usage (void)
" status\n"
" list [iface <iface>]\n"
" disconnect iface <iface> [--nowait] [--timeout <timeout>]\n"
" wifi [list [iface <iface>] | apinfo iface <iface> hwaddr <hwaddr>]\n\n"));
" wifi [list [iface <iface>] [hwaddr <hwaddr>]]\n\n"));
}
/* quit main loop */
@ -212,63 +241,94 @@ ip4_address_as_string (guint32 ip)
}
}
typedef struct {
NmCli *nmc;
const char* active_bssid;
const char* device;
} APInfo;
static void
detail_access_point (gpointer data, gpointer user_data)
{
NMAccessPoint *ap = NM_ACCESS_POINT (data);
const char *active_bssid = (const char *) user_data;
GString *str;
APInfo *info = (APInfo *) user_data;
gboolean active = FALSE;
guint32 flags, wpa_flags, rsn_flags;
const GByteArray * ssid;
char *tmp;
guint32 flags, wpa_flags, rsn_flags, freq, bitrate;
guint8 strength;
const GByteArray *ssid;
const char *hwaddr;
NM80211Mode mode;
char *freq_str, *ssid_str, *bitrate_str, *strength_str, *wpa_flags_str, *rsn_flags_str;
GString *security_str;
flags = nm_access_point_get_flags (ap);
wpa_flags = nm_access_point_get_wpa_flags (ap);
rsn_flags = nm_access_point_get_rsn_flags (ap);
if (active_bssid) {
if (info->active_bssid) {
const char *current_bssid = nm_access_point_get_hw_address (ap);
if (current_bssid && !strcmp (current_bssid, active_bssid))
if (current_bssid && !strcmp (current_bssid, info->active_bssid))
active = TRUE;
}
str = g_string_new (NULL);
g_string_append_printf (str,
_("%s, %s, Freq %d MHz, Rate %d Mb/s, Strength %d"),
(nm_access_point_get_mode (ap) == NM_802_11_MODE_INFRA) ? ("Infra") : _("Ad-Hoc"),
nm_access_point_get_hw_address (ap),
nm_access_point_get_frequency (ap),
nm_access_point_get_max_bitrate (ap) / 1000,
nm_access_point_get_strength (ap));
/* Get AP properties */
flags = nm_access_point_get_flags (ap);
wpa_flags = nm_access_point_get_wpa_flags (ap);
rsn_flags = nm_access_point_get_rsn_flags (ap);
ssid = nm_access_point_get_ssid (ap);
hwaddr = nm_access_point_get_hw_address (ap);
freq = nm_access_point_get_frequency (ap);
mode = nm_access_point_get_mode (ap);
bitrate = nm_access_point_get_max_bitrate (ap);
strength = nm_access_point_get_strength (ap);
/* Convert to strings */
ssid_str = g_strdup_printf ("%s", ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : _("(none)"));
freq_str = g_strdup_printf (_("%u MHz"), freq);
bitrate_str = g_strdup_printf (_("%u MB/s"), bitrate/1000);
strength_str = g_strdup_printf ("%u", strength);
wpa_flags_str = ap_wpa_rsn_flags_to_string (wpa_flags);
rsn_flags_str = ap_wpa_rsn_flags_to_string (rsn_flags);
security_str = g_string_new (NULL);
if ( !(flags & NM_802_11_AP_FLAGS_PRIVACY)
&& (wpa_flags != NM_802_11_AP_SEC_NONE)
&& (rsn_flags != NM_802_11_AP_SEC_NONE))
g_string_append (str, _(", Encrypted: "));
g_string_append (security_str, _("Encrypted: "));
if ( (flags & NM_802_11_AP_FLAGS_PRIVACY)
&& (wpa_flags == NM_802_11_AP_SEC_NONE)
&& (rsn_flags == NM_802_11_AP_SEC_NONE))
g_string_append (str, _(" WEP"));
g_string_append (security_str, _("WEP "));
if (wpa_flags != NM_802_11_AP_SEC_NONE)
g_string_append (str, _(" WPA"));
g_string_append (security_str, _("WPA "));
if (rsn_flags != NM_802_11_AP_SEC_NONE)
g_string_append (str, _(" WPA2"));
g_string_append (security_str, _("WPA2 "));
if ( (wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
|| (rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
g_string_append (str, _(" Enterprise"));
g_string_append (security_str, _("Enterprise "));
/* FIXME: broadcast/hidden */
if (security_str->len > 0)
g_string_truncate (security_str, security_str->len-1); /* Chop off last space */
ssid = nm_access_point_get_ssid (ap);
tmp = g_strdup_printf (" %s%s", active ? "*" : "",
ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : _("(none)"));
info->nmc->allowed_fields[0].value = ssid_str;
info->nmc->allowed_fields[1].value = hwaddr;
info->nmc->allowed_fields[2].value = mode == NM_802_11_MODE_ADHOC ? _("Ad-Hoc") : mode == NM_802_11_MODE_INFRA ? _("Infrastructure") : _("Unknown");
info->nmc->allowed_fields[3].value = freq_str;
info->nmc->allowed_fields[4].value = bitrate_str;
info->nmc->allowed_fields[5].value = strength_str;
info->nmc->allowed_fields[6].value = security_str->str;
info->nmc->allowed_fields[7].value = wpa_flags_str;
info->nmc->allowed_fields[8].value = rsn_flags_str;
info->nmc->allowed_fields[9].value = info->device;
info->nmc->allowed_fields[10].value = active ? _("yes") : _("no");
print_table_line (0, tmp, 25, str->str, 0, NULL);
info->nmc->print_fields.flags &= ~NMC_PF_FLAG_HEADER; /* Clear HEADER flag */
print_fields (info->nmc->print_fields, info->nmc->allowed_fields);
g_string_free (str, TRUE);
g_free (tmp);
g_free (ssid_str);
g_free (freq_str);
g_free (bitrate_str);
g_free (strength_str);
g_free (wpa_flags_str);
g_free (rsn_flags_str);
g_string_free (security_str, TRUE);
}
struct cb_info {
@ -280,7 +340,8 @@ static void
show_device_info (gpointer data, gpointer user_data)
{
NMDevice *device = NM_DEVICE (data);
// struct cb_info *info = user_data;
NmCli *nmc = (NmCli *) user_data;
APInfo *info;
char *tmp;
NMDeviceState state;
const char *dev_type;
@ -365,11 +426,21 @@ show_device_info (gpointer data, gpointer user_data)
active_bssid = active_ap ? nm_access_point_get_hw_address (active_ap) : NULL;
}
printf (_("\n Wireless Access Points %s\n"), active_ap ? _("(* = current AP)") : "");
printf (_("\n Wireless Access Points\n"));
nmc->print_fields.flags = NMC_PF_FLAG_HEADER;
nmc->print_fields.indent = 2; /* Indent by 2 spaces */
nmc->print_fields.indices = parse_output_fields (NMC_FIELDS_DEV_WIFI_LIST_COMMON, nmc->allowed_fields, NULL);
print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
info = g_malloc0 (sizeof (APInfo));
info->nmc = nmc;
info->active_bssid = active_bssid;
info->device = nm_device_get_iface (device);
aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
if (aps && aps->len)
g_ptr_array_foreach ((GPtrArray *) aps, detail_access_point, (gpointer) active_bssid);
g_ptr_array_foreach ((GPtrArray *) aps, detail_access_point, (gpointer) info);
g_free (info);
} else if (NM_IS_DEVICE_ETHERNET (device)) {
printf (_("\n Wired Properties\n"));
@ -425,22 +496,26 @@ show_device_info (gpointer data, gpointer user_data)
static void
show_device_status (NMDevice *device, NmCli *nmc)
{
const char *iface;
const char *type;
const char *state;
nmc->allowed_fields[0].value = nm_device_get_iface (device);
nmc->allowed_fields[1].value = get_device_type (device);
nmc->allowed_fields[2].value = device_state_to_string (nm_device_get_state (device));
iface = nm_device_get_iface (device);
type = get_device_type (device);
state = device_state_to_string (nm_device_get_state (device));
print_table_line (0, iface, 10, type, 17, state, 0, NULL);
nmc->print_fields.flags &= ~NMC_PF_FLAG_HEADER; /* Clear HEADER flag */
print_fields (nmc->print_fields, nmc->allowed_fields);
}
static NMCResultCode
do_devices_status (NmCli *nmc, int argc, char **argv)
{
GError *error = NULL;
const GPtrArray *devices;
int i;
char *fields_str;
char *fields_all = NMC_FIELDS_DEV_STATUS_ALL;
char *fields_common = NMC_FIELDS_DEV_STATUS_COMMON;
guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
while (argc > 0) {
fprintf (stderr, _("Unknown parameter: %s\n"), *argv);
@ -454,10 +529,26 @@ do_devices_status (NmCli *nmc, int argc, char **argv)
devices = nm_client_get_devices (nmc->client);
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("Status of devices"), _("Device"), 10, _("Type"), 17, _("State"), 12, NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("Device"), 10, _("Type"), 17, _("State"), 0, NULL);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
fields_str = fields_all;
else
fields_str = nmc->required_fields;
nmc->allowed_fields = nmc_fields_dev_status;
nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error);
if (error) {
g_string_printf (nmc->return_text, error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("Status of devices");
print_fields (nmc->print_fields, nmc->allowed_fields);
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *device = g_ptr_array_index (devices, i);
@ -504,6 +595,9 @@ do_devices_list (NmCli *nmc, int argc, char **argv)
devices = nm_client_get_devices (nmc->client);
/* Set allowed fields for use while printing in detail_access_point() */
nmc->allowed_fields = nmc_fields_dev_wifi_list;
if (iface_specified) {
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
@ -517,10 +611,10 @@ do_devices_list (NmCli *nmc, int argc, char **argv)
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
show_device_info (device, nmc->client);
show_device_info (device, nmc);
} else {
if (devices)
g_ptr_array_foreach ((GPtrArray *) devices, show_device_info, nmc->client);
g_ptr_array_foreach ((GPtrArray *) devices, show_device_info, nmc);
}
error:
@ -665,119 +759,46 @@ error:
}
static void
show_acces_point_info (NMDevice *device)
show_acces_point_info (NMDevice *device, NmCli *nmc)
{
NMAccessPoint *active_ap = NULL;
const char *active_bssid = NULL;
const GPtrArray *aps;
APInfo *info;
if (nm_device_get_state (device) == NM_DEVICE_STATE_ACTIVATED) {
active_ap = nm_device_wifi_get_active_access_point (NM_DEVICE_WIFI (device));
active_bssid = active_ap ? nm_access_point_get_hw_address (active_ap) : NULL;
}
info = g_malloc0 (sizeof (APInfo));
info->nmc = nmc;
info->active_bssid = active_bssid;
info->device = nm_device_get_iface (device);
aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
if (aps && aps->len)
g_ptr_array_foreach ((GPtrArray *) aps, detail_access_point, (gpointer) active_bssid);
g_ptr_array_foreach ((GPtrArray *) aps, detail_access_point, (gpointer) info);
g_free (info);
}
static NMCResultCode
do_device_wifi_list (NmCli *nmc, int argc, char **argv)
{
//TODO: cleanup
const GPtrArray *devices;
GError *error = NULL;
NMDevice *device = NULL;
const char *iface = NULL;
gboolean iface_specified = FALSE;
int i;
while (argc > 0) {
if (strcmp (*argv, "iface") == 0) {
iface_specified = TRUE;
if (next_arg (&argc, &argv) != 0) {
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), *argv);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
iface = *argv;
} else {
fprintf (stderr, _("Unknown parameter: %s\n"), *argv);
}
argc--;
argv++;
}
/* create NMClient */
if (!nmc->get_client (nmc))
goto error;
devices = nm_client_get_devices (nmc->client);
if (iface_specified) {
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
const char *dev_iface = nm_device_get_iface (candidate);
if (!strcmp (dev_iface, iface))
device = candidate;
}
if (!device) {
g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
if ((NM_IS_DEVICE_WIFI (device))) {
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("WiFi scan list"), NULL);
show_acces_point_info (device);
} else {
g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiFi device."), iface);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
} else {
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("WiFi scan list"), NULL);
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *dev = g_ptr_array_index (devices, i);
const char *dev_iface = nm_device_get_iface (dev);
if ((NM_IS_DEVICE_WIFI (dev))) {
if (nmc->print_output > NMC_PRINT_TERSE)
print_table_line (0, _("Device:"), 0, dev_iface, 0, NULL);
show_acces_point_info (dev);
}
}
}
error:
return nmc->return_value;
}
static NMCResultCode
do_device_wifi_apinfo (NmCli *nmc, int argc, char **argv)
{
const GPtrArray *devices;
const GPtrArray *aps;
NMAccessPoint *ap = NULL;
const char *iface = NULL;
const char *hwaddr_user = NULL;
const char *hwaddr;
gboolean stop = FALSE;
guint32 flags, wpa_flags, rsn_flags, freq, bitrate;
guint8 strength;
const GByteArray *ssid;
NM80211Mode mode;
char *freq_str, *ssid_str, *bitrate_str, *strength_str, *wpa_flags_str, *rsn_flags_str;
const GPtrArray *devices;
const GPtrArray *aps;
APInfo *info;
int i, j;
char *fields_str;
char *fields_all = NMC_FIELDS_DEV_WIFI_LIST_ALL;
char *fields_common = NMC_FIELDS_DEV_WIFI_LIST_COMMON;
guint32 mode_flag = (nmc->print_output == NMC_PRINT_PRETTY) ? NMC_PF_FLAG_PRETTY : (nmc->print_output == NMC_PRINT_TERSE) ? NMC_PF_FLAG_TERSE : 0;
guint32 multiline_flag = nmc->multiline_output ? NMC_PF_FLAG_MULTILINE : 0;
guint32 escape_flag = nmc->escape_values ? NMC_PF_FLAG_ESCAPE : 0;
while (argc > 0) {
if (strcmp (*argv, "iface") == 0) {
@ -802,90 +823,129 @@ do_device_wifi_apinfo (NmCli *nmc, int argc, char **argv)
argv++;
}
if (!hwaddr_user) {
g_string_printf (nmc->return_text, _("Error: hwaddr has to be specified."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
/* create NMClient */
if (!nmc->get_client (nmc))
goto error;
devices = nm_client_get_devices (nmc->client);
for (i = 0; !stop && devices && (i < devices->len); i++) {
NMDevice *device = g_ptr_array_index (devices, i);
const char *dev_iface = nm_device_get_iface (device);
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0)
fields_str = fields_common;
else if (!nmc->required_fields || strcasecmp (nmc->required_fields, "all") == 0)
fields_str = fields_all;
else
fields_str = nmc->required_fields;
if (iface) {
if (!strcmp (iface, dev_iface))
stop = TRUE;
else
continue;
}
nmc->allowed_fields = nmc_fields_dev_wifi_list;
nmc->print_fields.indices = parse_output_fields (fields_str, nmc->allowed_fields, &error);
aps = NULL;
if ((NM_IS_DEVICE_WIFI (device)))
aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
for (j = 0; aps && (j < aps->len); j++) {
char *hwaddr_up;
NMAccessPoint *candidate_ap = g_ptr_array_index (aps, j);
const char *candidate_hwaddr = nm_access_point_get_hw_address (candidate_ap);
hwaddr_up = g_ascii_strup (hwaddr_user, -1);
if (!strcmp (hwaddr_up, candidate_hwaddr))
ap = candidate_ap;
g_free (hwaddr_up);
}
}
if (!ap) {
g_string_printf (nmc->return_text, _("Error: Access point with hwaddr '%s' not found."), hwaddr_user);
if (error) {
g_string_printf (nmc->return_text, error->message);
g_error_free (error);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
/* get AP properties */
flags = nm_access_point_get_flags (ap);
wpa_flags = nm_access_point_get_wpa_flags (ap);
rsn_flags = nm_access_point_get_rsn_flags (ap);
ssid = nm_access_point_get_ssid (ap);
hwaddr = nm_access_point_get_hw_address (ap);
freq = nm_access_point_get_frequency (ap);
mode = nm_access_point_get_mode (ap);
bitrate = nm_access_point_get_max_bitrate (ap);
strength = nm_access_point_get_strength (ap);
nmc->print_fields.flags = multiline_flag | mode_flag | escape_flag | NMC_PF_FLAG_HEADER;
nmc->print_fields.header_name = _("WiFi scan list");
/* print them */
ssid_str = g_strdup_printf ("%s", ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : _("(none)"));
freq_str = g_strdup_printf (_("%u MHz"), freq);
bitrate_str = g_strdup_printf (_("%u MB/s"), bitrate/1000);
strength_str = g_strdup_printf ("%u", strength);
wpa_flags_str = ap_wpa_rsn_flags_to_string (wpa_flags);
rsn_flags_str = ap_wpa_rsn_flags_to_string (rsn_flags);
if (iface) {
/* Device specified - list only APs of this interface */
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *candidate = g_ptr_array_index (devices, i);
const char *dev_iface = nm_device_get_iface (candidate);
if (nmc->print_output == NMC_PRINT_PRETTY)
print_table_header (_("AP parameters"), NULL);
else if (nmc->print_output == NMC_PRINT_NORMAL)
print_table_line (0, _("AP parameters"), 0, NULL);
if (!strcmp (dev_iface, iface)) {
device = candidate;
break;
}
}
print_table_line (0, _("SSID:"), 25, ssid_str, 0, NULL);
print_table_line (0, _("BSSID:"), 25, hwaddr, 0, NULL);
print_table_line (0, _("Frequency:"), 25, freq_str, 0, NULL);
print_table_line (0, _("Mode:"), 25, mode == NM_802_11_MODE_ADHOC ? _("Ad-hoc") : mode == NM_802_11_MODE_INFRA ? _("Infrastructure") : _("Unknown"), 0, NULL);
print_table_line (0, _("Maximal bitrate:"), 25, bitrate_str, 0, NULL);
print_table_line (0, _("Strength:"), 25, strength_str, 0, NULL);
print_table_line (0, _("Flags:"), 25, flags == NM_802_11_AP_FLAGS_PRIVACY ? _("privacy") : _("(none)"), 0, NULL);
print_table_line (0, _("WPA flags:"), 25, wpa_flags_str, 0, NULL);
print_table_line (0, _("RSN flags:"), 25, rsn_flags_str, 0, NULL);
if (!device) {
g_string_printf (nmc->return_text, _("Error: Device '%s' not found."), iface);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
g_free (ssid_str);
g_free (freq_str);
g_free (bitrate_str);
g_free (strength_str);
g_free (wpa_flags_str);
g_free (rsn_flags_str);
if (NM_IS_DEVICE_WIFI (device)) {
if (hwaddr_user) {
/* Specific AP requested - list only that */
aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device));
for (j = 0; aps && (j < aps->len); j++) {
char *hwaddr_up;
NMAccessPoint *candidate_ap = g_ptr_array_index (aps, j);
const char *candidate_hwaddr = nm_access_point_get_hw_address (candidate_ap);
hwaddr_up = g_ascii_strup (hwaddr_user, -1);
if (!strcmp (hwaddr_up, candidate_hwaddr))
ap = candidate_ap;
g_free (hwaddr_up);
}
if (!ap) {
g_string_printf (nmc->return_text, _("Error: Access point with hwaddr '%s' not found."), hwaddr_user);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
info = g_malloc0 (sizeof (APInfo));
info->nmc = nmc;
info->active_bssid = NULL;
info->device = nm_device_get_iface (device);
print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
detail_access_point (ap, info);
g_free (info);
} else {
print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
show_acces_point_info (device, nmc);
}
} else {
g_string_printf (nmc->return_text, _("Error: Device '%s' is not a WiFi device."), iface);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
} else {
/* List APs for all devices */
print_fields (nmc->print_fields, nmc->allowed_fields); /* Print header */
if (hwaddr_user) {
/* Specific AP requested - list only that */
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *dev = g_ptr_array_index (devices, i);
if (!NM_IS_DEVICE_WIFI (dev))
continue;
aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (dev));
for (j = 0; aps && (j < aps->len); j++) {
char *hwaddr_up;
NMAccessPoint *candidate_ap = g_ptr_array_index (aps, j);
const char *candidate_hwaddr = nm_access_point_get_hw_address (candidate_ap);
hwaddr_up = g_ascii_strup (hwaddr_user, -1);
if (!strcmp (hwaddr_up, candidate_hwaddr)) {
ap = candidate_ap;
info = g_malloc0 (sizeof (APInfo));
info->nmc = nmc;
info->active_bssid = NULL;
info->device = nm_device_get_iface (dev);
detail_access_point (ap, info);
g_free (info);
}
g_free (hwaddr_up);
}
}
if (!ap) {
g_string_printf (nmc->return_text, _("Error: Access point with hwaddr '%s' not found."), hwaddr_user);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
goto error;
}
} else {
for (i = 0; devices && (i < devices->len); i++) {
NMDevice *dev = g_ptr_array_index (devices, i);
if (NM_IS_DEVICE_WIFI (dev))
show_acces_point_info (dev, nmc);
}
}
}
error:
return nmc->return_value;
@ -900,9 +960,6 @@ do_device_wifi (NmCli *nmc, int argc, char **argv)
if (matches (*argv, "list") == 0) {
nmc->return_value = do_device_wifi_list (nmc, argc-1, argv+1);
}
else if (matches (*argv, "apinfo") == 0) {
nmc->return_value = do_device_wifi_apinfo (nmc, argc-1, argv+1);
}
else {
g_string_printf (nmc->return_text, _("Error: 'dev wifi' command '%s' is not valid."), *argv);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;

View file

@ -45,7 +45,7 @@
#include "devices.h"
#include "network-manager.h"
#define NMCLI_VERSION "0.1"
#define NMCLI_VERSION "0.2"
typedef struct {
@ -64,10 +64,13 @@ usage (const char *prog_name)
fprintf (stderr,
_("Usage: %s [OPTIONS] OBJECT { COMMAND | help }\n\n"
"OPTIONS\n"
" -t[erse] terse output\n"
" -p[retty] pretty output\n"
" -v[ersion] show program version\n"
" -h[elp] print this help\n\n"
" -t[erse] terse output\n"
" -p[retty] pretty output\n"
" -m[ultiline] multiline output\n"
" -f[ields] <field1,field2,...>|all|common specify fields to output\n"
" -e[scape] yes|no escape columns separators in values\n"
" -v[ersion] show program version\n"
" -h[elp] print this help\n\n"
"OBJECT\n"
" nm NetworkManager status\n"
" con NetworkManager connections\n"
@ -132,9 +135,57 @@ parse_command_line (NmCli *nmc, int argc, char **argv)
if (opt[1] == '-')
opt++;
if (matches (opt, "-terse") == 0) {
nmc->print_output = NMC_PRINT_TERSE;
if (nmc->print_output == NMC_PRINT_TERSE) {
g_string_printf (nmc->return_text, _("Option '--terse' is specified the second time."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
else if (nmc->print_output == NMC_PRINT_PRETTY) {
g_string_printf (nmc->return_text, _("Option '--terse' is mutually exclusive with '--pretty'."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
else
nmc->print_output = NMC_PRINT_TERSE;
} else if (matches (opt, "-pretty") == 0) {
nmc->print_output = NMC_PRINT_PRETTY;
if (nmc->print_output == NMC_PRINT_PRETTY) {
g_string_printf (nmc->return_text, _("Option '--pretty' is specified the second time."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
else if (nmc->print_output == NMC_PRINT_TERSE) {
g_string_printf (nmc->return_text, _("Option '--pretty' is mutually exclusive with '--terse'."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
else
nmc->print_output = NMC_PRINT_PRETTY;
} else if (matches (opt, "-multiline") == 0) {
nmc->multiline_output = TRUE;
} else if (matches (opt, "-escape") == 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_UNKNOWN;
return nmc->return_value;
}
if (!strcmp (argv[1], "yes"))
nmc->escape_values = TRUE;
else if (!strcmp (argv[1], "no"))
nmc->escape_values = FALSE;
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_UNKNOWN;
return nmc->return_value;
}
} else if (matches (opt, "-fields") == 0) {
next_arg (&argc, &argv);
if (argc <= 1) {
g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
nmc->required_fields = g_strdup (argv[1]);
} else if (matches (opt, "-version") == 0) {
printf (_("nmcli tool, version %s\n"), NMCLI_VERSION);
return NMC_RESULT_SUCCESS;
@ -150,6 +201,20 @@ parse_command_line (NmCli *nmc, int argc, char **argv)
argv++;
}
/* Some validity options checks */
if (nmc->print_output == NMC_PRINT_TERSE) {
if (!nmc->required_fields) {
g_string_printf (nmc->return_text, _("Option '--terse' requires specifying '--fields'."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
} else if ( !strcasecmp (nmc->required_fields, "all")
|| !strcasecmp (nmc->required_fields, "common")) {
g_string_printf (nmc->return_text, _("Option '--terse' requires specific '--fields' option, not 'all' or 'common'."));
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
return nmc->return_value;
}
}
if (argc > 1)
return do_cmd (nmc, argv[1], argc-1, argv+1);
@ -217,6 +282,11 @@ nmc_init (NmCli *nmc)
nmc->should_wait = FALSE;
nmc->print_output = NMC_PRINT_NORMAL;
nmc->multiline_output = FALSE;
nmc->escape_values = TRUE;
nmc->required_fields = NULL;
nmc->allowed_fields = NULL;
memset (&nmc->print_fields, '\0', sizeof (NmcPrintFields));
}
static void
@ -231,6 +301,10 @@ nmc_cleanup (NmCli *nmc)
g_slist_free (nmc->system_connections);
g_slist_free (nmc->user_connections);
g_free (nmc->required_fields);
if (nmc->print_fields.indices)
g_array_free (nmc->print_fields.indices, TRUE);
}
static gboolean

View file

@ -20,10 +20,12 @@
#ifndef NMC_NMCLI_H
#define NMC_NMCLI_H
#include <glib.h>
#include <nm-client.h>
#include <nm-remote-settings.h>
#include <nm-remote-settings-system.h>
/* nmcli exit codes */
typedef enum {
/* Indicates successful execution */
@ -51,27 +53,55 @@ typedef enum {
NMC_PRINT_PRETTY
} NMCPrintOutput;
/* === Output fields === */
typedef struct {
const char *name; /* Field's name */
const char *name_l10n; /* Field's name for translation */
int width; /* Width in screen columns */
const char *value; /* Value of current field */
guint32 flags; /* Flags */
} NmcOutputField;
/* Flags for NmcPrintFields */
#define NMC_PF_FLAG_MULTILINE 0x00000001 /* Multiline output instead of tabular*/
#define NMC_PF_FLAG_TERSE 0x00000002 /* Terse outpud mode */
#define NMC_PF_FLAG_PRETTY 0x00000004 /* Pretty output mode */
#define NMC_PF_FLAG_HEADER 0x00000008 /* Print headers instead of values */
#define NMC_PF_FLAG_ESCAPE 0x00000010 /* Escape column separator and '\' */
typedef struct {
GArray *indices; /* Array of field indices to the array of allowed fields */
char *header_name; /* Name of the output */
int indent; /* Indent by this number of spaces */
guint32 flags; /* Various flags for controlling output: see NMC_PF_FLAG_* values */
} NmcPrintFields;
/* NmCli - main structure */
typedef struct _NmCli {
NMClient *client;
NMClient *(*get_client) (struct _NmCli *nmc);
NMClient *client; /* Pointer to NMClient of libnm-glib */
NMClient *(*get_client) (struct _NmCli *nmc); /* Pointer to function for creating NMClient */
NMCResultCode return_value;
GString *return_text;
NMCResultCode return_value; /* Return code of nmcli */
GString *return_text; /* Reason text */
int timeout;
int timeout; /* Operation timeout */
NMRemoteSettingsSystem *system_settings;
NMRemoteSettings *user_settings;
NMRemoteSettingsSystem *system_settings; /* System settings */
NMRemoteSettings *user_settings; /* User settings */
gboolean system_settings_running;
gboolean user_settings_running;
gboolean system_settings_running; /* Is system settings service running? */
gboolean user_settings_running; /* Is user settings service running? */
GSList *system_connections;
GSList *user_connections;
GSList *system_connections; /* List of system connections */
GSList *user_connections; /* List of user connections */
gboolean should_wait;
NMCPrintOutput print_output;
gboolean should_wait; /* Indication that nmcli should not end yet */
NMCPrintOutput print_output; /* Output mode */
gboolean multiline_output; /* Multiline output instead of default tabular */
gboolean escape_values; /* Whether to escape ':' and '\' in terse tabular mode */
char *required_fields; /* Required fields in output: '--fields' option */
NmcOutputField *allowed_fields; /* Array of allowed fields for particular commands */
NmcPrintFields print_fields; /* Structure with field indices to print */
} NmCli;
#endif /* NMC_NMCLI_H */

View file

@ -21,6 +21,7 @@
#include <string.h>
#include <glib.h>
#include <glib/gi18n.h>
#include "utils.h"
@ -46,6 +47,171 @@ next_arg (int *argc, char ***argv)
return 0;
}
/*
* Parse comma separated fields in 'fields_str' according to 'fields_array'.
* IN: 'field_str': comma-separated fields names
* 'fields_array': array of allowed fields
* RETURN: GArray with indices representing fields in 'fields_array'.
*/
GArray *
parse_output_fields (const char *fields_str, const NmcOutputField fields_array[], GError **error)
{
char **fields, **iter;
GArray *array;
int i;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
array = g_array_new (FALSE, FALSE, sizeof (int));
/* Split supplied fields string */
fields = g_strsplit_set (fields_str, ",", -1);
for (iter = fields; iter && *iter; iter++) {
for (i = 0; fields_array[i].name; i++) {
if (strcasecmp (*iter, fields_array[i].name) == 0) {
g_array_append_val (array, i);
break;
}
}
if (fields_array[i].name == NULL) {
if (!strcasecmp (*iter, "all") || !strcasecmp (*iter, "common"))
g_set_error (error, 0, 0, _("Error: 'con status': field '%s' has to be alone."), *iter);
else
g_set_error (error, 0, 0, _("Error: 'con status': invalid field '%s'."), *iter);
g_array_free (array, TRUE);
array = NULL;
goto done;
}
}
done:
return array;
}
void
print_fields (const NmcPrintFields fields, const NmcOutputField field_values[])
{
GString *str;
int width1, width2;
int table_width = 0;
char *line = NULL;
char *indent_str;
const char *value;
int i, idx;
gboolean multiline = fields.flags & NMC_PF_FLAG_MULTILINE;
gboolean terse = fields.flags & NMC_PF_FLAG_TERSE;
gboolean pretty = fields.flags & NMC_PF_FLAG_PRETTY;
gboolean header = fields.flags & NMC_PF_FLAG_HEADER;
gboolean escape = fields.flags & NMC_PF_FLAG_ESCAPE;
/* Headers are not printed in terse mode */
if (header && terse)
return;
if (multiline) {
/* --- Multiline mode --- */
if (header && pretty) {
/* Print the table header */
table_width = g_utf8_strlen (fields.header_name, -1) + 4;
line = g_strnfill (79, '=');
width1 = strlen (fields.header_name);
width2 = g_utf8_strlen (fields.header_name, -1);
printf ("%s\n", line);
printf ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name);
printf ("%s\n", line);
g_free (line);
}
/* Print values */
if (!header) {
for (i = 0; i < fields.indices->len; i++) {
char *tmp;
idx = g_array_index (fields.indices, int, i);
tmp = g_strdup_printf ("%s:", _(field_values[idx].name_l10n));
printf ("%-*s%s\n", terse ? 0 : 20, tmp, field_values[idx].value);
g_free (tmp);
}
if (pretty) {
line = g_strnfill (79, '-');
printf ("%s\n", line);
g_free (line);
}
}
return;
}
/* --- Tabular mode: each line = one object --- */
str = g_string_new (NULL);
for (i = 0; i < fields.indices->len; i++) {
idx = g_array_index (fields.indices, int, i);
if (header)
value = _(field_values[idx].name_l10n);
else
value = field_values[idx].value;
if (terse) {
if (escape) {
const char *p = value;
while (*p) {
if (*p == ':' || *p == '\\')
g_string_append_c (str, '\\'); /* Escaping by '\' */
g_string_append_c (str, *p);
p++;
}
}
else
g_string_append_printf (str, "%s", value);
g_string_append_c (str, ':'); /* Column separator */
} else {
width1 = strlen (value);
width2 = g_utf8_strlen (value, -1); /* Width of the string (in screen colums) */
if (strlen (value) == 0)
value = "--";
g_string_append_printf (str, "%-*s", field_values[idx].width + width1 - width2, value);
g_string_append_c (str, ' '); /* Column separator */
table_width += field_values[idx].width + width1 - width2 + 1;
}
}
if (table_width <= 0)
table_width = g_utf8_strlen (fields.header_name, -1) + 4;
if (header && pretty) {
/* Print the table header */
line = g_strnfill (table_width, '=');
width1 = strlen (fields.header_name);
width2 = g_utf8_strlen (fields.header_name, -1);
printf ("%s\n", line);
printf ("%*s\n", (table_width + width2)/2 + width1 - width2, fields.header_name);
printf ("%s\n", line);
g_free (line);
}
/* Print the line */
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, ' ');
g_string_prepend (str, indent_str);
g_free (indent_str);
}
printf ("%s\n", str->str);
}
if (header && pretty) {
if (str->len > 0) {
line = g_strnfill (table_width, '-');
printf ("%s\n", line);
g_free (line);
}
}
g_string_free (str, TRUE);
}
/*--- obsolete printing functions ---*/
void
print_table_header (const char *name, ...)
{

View file

@ -20,8 +20,15 @@
#ifndef NMC_UTILS_H
#define NMC_UTILS_H
#include <glib.h>
#include "nmcli.h"
/* === Functions === */
int matches (const char *cmd, const char *pattern);
int next_arg (int *argc, char ***argv);
GArray *parse_output_fields (const char *fields_str, const NmcOutputField fields_array[], GError **error);
void print_fields (const NmcPrintFields fields, const NmcOutputField field_values[]);
void print_table_header (const char *name, ...);
void print_table_line (int indent, ...);