merge: branch 'lr/nmcli-monitor-rh1034158'

https://bugzilla.redhat.com/show_bug.cgi?id=1034158
This commit is contained in:
Lubomir Rintel
2015-12-05 12:28:21 +01:00
15 changed files with 612 additions and 224 deletions

View File

@@ -144,7 +144,7 @@ do_agent_secret (NmCli *nmc, int argc, char **argv)
nmc->secret_agent = nm_secret_agent_simple_new ("nmcli-agent");
if (nmc->secret_agent) {
/* We keep running */
nmc->should_wait = TRUE;
nmc->should_wait++;
nm_secret_agent_simple_enable (NM_SECRET_AGENT_SIMPLE (nmc->secret_agent), NULL);
g_signal_connect (nmc->secret_agent, "request-secrets", G_CALLBACK (secrets_requested), nmc);
@@ -171,7 +171,7 @@ do_agent_polkit (NmCli *nmc, int argc, char **argv)
g_error_free (error);
} else {
/* We keep running */
nmc->should_wait = TRUE;
nmc->should_wait++;
g_print (_("nmcli successfully registered as a polkit agent.\n"));
}

View File

@@ -261,7 +261,7 @@ static void
usage (void)
{
g_printerr (_("Usage: nmcli connection { COMMAND | help }\n\n"
"COMMAND := { show | up | down | add | modify | edit | delete | reload | load }\n\n"
"COMMAND := { show | up | down | add | modify | edit | delete | monitor | reload | load }\n\n"
" show [--active] [--order <order spec>]\n"
" show [--active] [--show-secrets] [id | uuid | path | apath] <ID> ...\n\n"
" up [[id | uuid | path] <ID>] [ifname <ifname>] [ap <BSSID>] [passwd-file <file with passwords>]\n\n"
@@ -272,6 +272,7 @@ usage (void)
" edit [id | uuid | path] <ID>\n"
" edit [type <new_con_type>] [con-name <new_con_name>]\n\n"
" delete [id | uuid | path] <ID>\n\n"
" monitor [id | uuid | path] <ID> ...\n\n"
" reload\n\n"
" load <filename> [ <filename>... ]\n\n"));
}
@@ -489,6 +490,18 @@ usage_connection_delete (void)
"The profile is identified by its name, UUID or D-Bus path.\n\n"));
}
static void
usage_connection_monitor (void)
{
g_printerr (_("Usage: nmcli connection monitor { ARGUMENTS | help }\n"
"\n"
"ARGUMENTS := [id | uuid | path] <ID> ...\n"
"\n"
"Monitor connection profile activity.\n"
"This command prints a line whenever the specified connection changes.\n"
"Monitors all connection profiles in case none is specified.\n\n"));
}
static void
usage_connection_reload (void)
{
@@ -530,6 +543,8 @@ usage_connection_second_level (const char *cmd)
usage_connection_edit ();
else if (matches (cmd, "delete") == 0)
usage_connection_delete ();
else if (matches (cmd, "monitor") == 0)
usage_connection_monitor ();
else if (matches (cmd, "reload") == 0)
usage_connection_reload ();
else if (matches (cmd, "load") == 0)
@@ -1535,8 +1550,6 @@ do_connections_show (NmCli *nmc, gboolean active_only, gboolean show_secrets,
char *profile_flds = NULL, *active_flds = NULL;
GPtrArray *invisibles, *sorted_cons;
nmc->should_wait = FALSE;
if (argc == 0) {
char *fields_str;
char *fields_all = NMC_FIELDS_CON_SHOW_ALL;
@@ -2377,13 +2390,14 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
* and we can follow activation progress.
*/
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
if (!nmc_activate_connection (nmc, connection, ifname, ap, nsp, pwds, activate_connection_cb, &error)) {
g_string_printf (nmc->return_text, _("Error: %s."),
error ? error->message : _("unknown error"));
nmc->return_value = error ? error->code : NMC_RESULT_ERROR_CON_ACTIVATION;
g_clear_error (&error);
nmc->should_wait--;
goto error;
}
@@ -2391,10 +2405,7 @@ do_connection_up (NmCli *nmc, int argc, char **argv)
if (nmc->print_output == NMC_PRINT_PRETTY)
progress_id = g_timeout_add (120, progress_cb, _("preparing"));
g_free (line);
return nmc->return_value;
error:
nmc->should_wait = FALSE;
g_free (line);
return nmc->return_value;
}
@@ -2549,7 +2560,7 @@ do_connection_down (NmCli *nmc, int argc, char **argv)
queue = g_slist_reverse (queue);
if (nmc->timeout > 0) {
nmc->should_wait = TRUE;
nmc->should_wait++;
info = g_slice_new0 (ConnectionCbInfo);
info->nmc = nmc;
@@ -6586,7 +6597,7 @@ do_connection_add (NmCli *nmc, int argc, char **argv)
goto error;
}
nmc->should_wait = TRUE;
nmc->should_wait++;
info = g_malloc0 (sizeof (AddConnectionInfo));
info->nmc = nmc;
@@ -6610,7 +6621,6 @@ error:
g_free (type_ask);
g_free (ifname_ask);
nmc->should_wait = FALSE;
return nmc->return_value;
}
@@ -8017,7 +8027,7 @@ property_edit_submenu (NmCli *nmc,
/* Set global variable for use in TAB completion */
nmc_tab_completion.property = prop_name;
prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s.%s> ",
nm_setting_get_name (curr_setting), prop_name);
@@ -8345,13 +8355,14 @@ typedef struct {
} NmcEditorMenuContext;
static void
menu_switch_to_level0 (NmcEditorMenuContext *menu_ctx,
menu_switch_to_level0 (NmCli *nmc,
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 (prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL, "%s", prompt);
menu_ctx->curr_setting = NULL;
g_strfreev (menu_ctx->valid_props);
menu_ctx->valid_props = NULL;
@@ -8360,14 +8371,15 @@ menu_switch_to_level0 (NmcEditorMenuContext *menu_ctx,
}
static void
menu_switch_to_level1 (NmcEditorMenuContext *menu_ctx,
menu_switch_to_level1 (NmCli *nmc,
NmcEditorMenuContext *menu_ctx,
NMSetting *setting,
const char *setting_name,
NmcTermColor prompt_color)
{
menu_ctx->level = 1;
g_free (menu_ctx->main_prompt);
menu_ctx->main_prompt = nmc_colorize (prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx->main_prompt = nmc_colorize (nmc, prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ", setting_name);
menu_ctx->curr_setting = setting;
g_strfreev (menu_ctx->valid_props);
@@ -8402,7 +8414,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->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
menu_ctx.curr_setting = NULL;
menu_ctx.valid_props = NULL;
@@ -8561,7 +8573,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 (&menu_ctx, setting, setting_name, nmc->editor_prompt_color);
menu_switch_to_level1 (nmc, &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);
@@ -8635,7 +8647,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 (&menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
} else {
@@ -8658,7 +8670,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 (&menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
} else
@@ -8957,7 +8969,7 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
}
nmc->nowait_flag = FALSE;
nmc->should_wait = TRUE;
nmc->should_wait++;
nmc->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)) {
@@ -9000,7 +9012,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 (&menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
menu_switch_to_level0 (nmc, &menu_ctx, BASE_PROMPT, nmc->editor_prompt_color);
nmc_tab_completion.setting = NULL; /* for TAB completion */
}
break;
@@ -9046,10 +9058,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->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
BASE_PROMPT);
else
menu_ctx.main_prompt = nmc_colorize (nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
menu_ctx.main_prompt = nmc_colorize (nmc, nmc->editor_prompt_color, NMC_TERM_FORMAT_NORMAL,
"nmcli %s> ",
nm_setting_get_name (menu_ctx.curr_setting));
}
@@ -9431,14 +9443,14 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
g_object_unref (connection);
g_free (nmc_tab_completion.con_type);
nmc->should_wait = TRUE;
nmc->should_wait++;
return nmc->return_value;
error:
g_assert (!connection);
g_free (type_ask);
nmc->should_wait = FALSE;
nmc->should_wait++;
return nmc->return_value;
}
@@ -9481,7 +9493,6 @@ do_connection_modify (NmCli *nmc,
GError *error = NULL;
nmc->return_value = NMC_RESULT_SUCCESS;
nmc->should_wait = FALSE;
if (argc == 0) {
g_string_printf (nmc->return_text, _("Error: No arguments provided."));
@@ -9536,7 +9547,7 @@ do_connection_modify (NmCli *nmc,
update_connection (!temporary, rc, modify_connection_cb, nmc);
nmc->should_wait = TRUE;
nmc->should_wait++;
finish:
return nmc->return_value;
}
@@ -9783,7 +9794,7 @@ do_connection_delete (NmCli *nmc, int argc, char **argv)
info->timeout_id = g_timeout_add_seconds (nmc->timeout, connection_op_timeout_cb, info);
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_REMOVED,
G_CALLBACK (connection_removed_cb), info);
@@ -9805,13 +9816,108 @@ finish:
return nmc->return_value;
}
static void
connection_changed (NMConnection *connection, NmCli *nmc)
{
g_print (_("%s: connection profile changed\n"), nm_connection_get_id (connection));
}
static void
connection_watch (NmCli *nmc, NMConnection *connection)
{
nmc->should_wait++;
g_signal_connect (connection, NM_CONNECTION_CHANGED, G_CALLBACK (connection_changed), nmc);
}
static void
connection_unwatch (NmCli *nmc, NMConnection *connection)
{
if (g_signal_handlers_disconnect_by_func (connection, G_CALLBACK (connection_changed), nmc))
nmc->should_wait--;
/* Terminate if all the watched connections disappeared. */
if (!nmc->should_wait)
quit ();
}
static void
connection_added (NMClient *client, NMRemoteConnection *con, NmCli *nmc)
{
NMConnection *connection = NM_CONNECTION (con);
g_print (_("%s: connection profile created\n"), nm_connection_get_id (connection));
connection_watch (nmc, connection);
}
static void
connection_removed (NMClient *client, NMRemoteConnection *con, NmCli *nmc)
{
NMConnection *connection = NM_CONNECTION (con);
g_print (_("%s: connection profile removed\n"), nm_connection_get_id (connection));
connection_unwatch (nmc, connection);
}
static NMCResultCode
do_connection_monitor (NmCli *nmc, int argc, char **argv)
{
if (argc == 0) {
/* No connections specified. Monitor all. */
int i;
nmc->connections = nm_client_get_connections (nmc->client);
for (i = 0; i < nmc->connections->len; i++)
connection_watch (nmc, g_ptr_array_index (nmc->connections, i));
/* We'll watch the connection additions too, never exit. */
nmc->should_wait++;
g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_ADDED, G_CALLBACK (connection_added), nmc);
} else {
/* Look up the specified connections and watch them. */
NMConnection *connection;
char **arg_ptr = argv;
int arg_num = argc;
int pos = 0;
do {
const char *selector = NULL;
if ( strcmp (*arg_ptr, "id") == 0
|| strcmp (*arg_ptr, "uuid") == 0
|| strcmp (*arg_ptr, "path") == 0) {
selector = *arg_ptr;
if (next_arg (&arg_num, &arg_ptr) != 0) {
g_string_printf (nmc->return_text, _("Error: %s argument is missing."), selector);
return NMC_RESULT_ERROR_USER_INPUT;
}
}
connection = nmc_find_connection (nmc->connections, selector, *arg_ptr, &pos);
if (connection) {
connection_watch (nmc, connection);
} else {
g_printerr (_("Error: unknown connection '%s'\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all connections found."));
return NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument (if there's no other connection of the same name) */
if (!pos)
next_arg (&arg_num, &arg_ptr);
} while (arg_num > 0);
}
g_signal_connect (nmc->client, NM_CLIENT_CONNECTION_REMOVED, G_CALLBACK (connection_removed), nmc);
return NMC_RESULT_SUCCESS;
}
static NMCResultCode
do_connection_reload (NmCli *nmc, int argc, char **argv)
{
GError *error = NULL;
nmc->return_value = NMC_RESULT_SUCCESS;
nmc->should_wait = FALSE;
if (!nm_client_reload_connections (nmc->client, NULL, &error)) {
g_string_printf (nmc->return_text, _("Error: failed to reload connections: %s."),
@@ -9831,7 +9937,6 @@ do_connection_load (NmCli *nmc, int argc, char **argv)
int i;
nmc->return_value = NMC_RESULT_SUCCESS;
nmc->should_wait = FALSE;
if (argc == 0) {
g_string_printf (nmc->return_text, _("Error: No connection specified."));
@@ -10113,7 +10218,7 @@ do_connections (NmCli *nmc, int argc, char **argv)
} else if (matches(*argv, "add") == 0) {
nmc->return_value = do_connection_add (nmc, argc-1, argv+1);
} else if (matches(*argv, "edit") == 0) {
nmc->should_wait = TRUE;
nmc->should_wait++;
editor_thread_data.nmc = nmc;
editor_thread_data.argc = argc - 1;
editor_thread_data.argv = argv + 1;
@@ -10121,6 +10226,8 @@ do_connections (NmCli *nmc, int argc, char **argv)
g_thread_unref (editor_thread);
} else if (matches(*argv, "delete") == 0) {
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
} else if (matches(*argv, "monitor") == 0) {
nmc->return_value = do_connection_monitor (nmc, argc-1, argv+1);
} else if (matches(*argv, "reload") == 0) {
nmc->return_value = do_connection_reload (nmc, argc-1, argv+1);
} else if (matches(*argv, "load") == 0) {
@@ -10158,3 +10265,9 @@ opt_error:
g_error_free (error);
return nmc->return_value;
}
void
monitor_connections (NmCli *nmc)
{
do_connection_monitor (nmc, 0, NULL);
}

View File

@@ -24,4 +24,6 @@
NMCResultCode do_connections (NmCli *nmc, int argc, char **argv);
void monitor_connections (NmCli *nmc);
#endif /* NMC_CONNECTIONS_H */

View File

@@ -282,13 +282,14 @@ static void
usage (void)
{
g_printerr (_("Usage: nmcli device { COMMAND | help }\n\n"
"COMMAND := { status | show | connect | disconnect | delete | wifi | lldp }\n\n"
"COMMAND := { status | show | connect | disconnect | delete | monitor | wifi | lldp }\n\n"
" status\n\n"
" show [<ifname>]\n\n"
" set [ifname] <ifname> [autoconnect yes|no] [managed yes|no]\n\n"
" connect <ifname>\n\n"
" disconnect <ifname> ...\n\n"
" delete <ifname> ...\n\n"
" monitor <ifname> ...\n\n"
" wifi [list [ifname <ifname>] [bssid <BSSID>]]\n\n"
" wifi connect <(B)SSID> [password <password>] [wep-key-type key|phrase] [ifname <ifname>]\n"
" [bssid <BSSID>] [name <name>] [private yes|no] [hidden yes|no]\n\n"
@@ -375,6 +376,18 @@ usage_device_set (void)
"Modify device properties.\n\n"));
}
static void
usage_device_monitor (void)
{
g_printerr (_("Usage: nmcli device monitor { ARGUMENTS | help }\n"
"\n"
"ARGUMENTS := [<ifname>] ...\n"
"\n"
"Monitor device activity.\n"
"This command prints a line whenever the specified devices change state.\n"
"Monitors all devices in case no interface is specified.\n\n"));
}
static void
usage_device_wifi (void)
{
@@ -484,6 +497,63 @@ get_devices_sorted (NMClient *client)
return sorted;
}
static GSList *
device_list (NmCli *nmc, int argc, char **argv)
{
int arg_num = argc;
char **arg_arr = NULL;
char **arg_ptr = argv;
NMDevice **devices;
GSList *queue = NULL;
NMDevice *device;
int i;
if (argc == 0) {
if (nmc->ask) {
char *line = nmc_readline (PROMPT_INTERFACES);
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
g_free (line);
arg_ptr = arg_arr;
}
if (arg_num == 0) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
goto error;
}
}
devices = get_devices_sorted (nmc->client);
while (arg_num > 0) {
device = NULL;
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
device = devices[i];
break;
}
}
if (device) {
if (!g_slist_find (queue, device))
queue = g_slist_prepend (queue, device);
else
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
} else {
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices found."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument */
next_arg (&arg_num, &arg_ptr);
}
g_free (devices);
error:
g_strfreev (arg_arr);
return queue;
}
static int
compare_aps (gconstpointer a, gconstpointer b, gpointer user_data)
{
@@ -1184,11 +1254,28 @@ show_device_info (NMDevice *device, NmCli *nmc)
return TRUE;
}
static ColorInfo
device_state_to_color (NMDeviceState state)
{
ColorInfo color_info = { NMC_TERM_COLOR_NORMAL, NMC_TERM_FORMAT_NORMAL };
if (state <= NM_DEVICE_STATE_UNAVAILABLE)
color_info.color_fmt= NMC_TERM_FORMAT_DIM;
else if (state == NM_DEVICE_STATE_DISCONNECTED)
color_info.color = NMC_TERM_COLOR_RED;
else if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_SECONDARIES)
color_info.color = NMC_TERM_COLOR_YELLOW;
else if (state == NM_DEVICE_STATE_ACTIVATED)
color_info.color = NMC_TERM_COLOR_GREEN;
return color_info;
}
static void
fill_output_device_status (NMDevice *device, NmCli *nmc)
{
NMActiveConnection *ac;
NMDeviceState state;
ColorInfo color_info;
NmcOutputField *arr = nmc_dup_fields_array (nmc_fields_dev_status,
sizeof (nmc_fields_dev_status),
0);
@@ -1197,14 +1284,9 @@ fill_output_device_status (NMDevice *device, NmCli *nmc)
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);
color_info = device_state_to_color (state);
set_val_color_all (arr, color_info.color);
set_val_color_fmt_all (arr, color_info.color_fmt);
set_val_strc (arr, 0, nm_device_get_iface (device));
set_val_strc (arr, 1, nm_device_get_type_description (device));
@@ -1622,7 +1704,7 @@ do_device_connect (NmCli *nmc, int argc, char **argv)
* till connect_device_cb() is called, giving NM time to check our permissions.
*/
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
/* Create secret agent */
nmc->secret_agent = nm_secret_agent_simple_new ("nmcli-connect");
@@ -1770,64 +1852,17 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
static NMCResultCode
do_device_disconnect (NmCli *nmc, int argc, char **argv)
{
NMDevice **devices;
NMDevice *device;
DeviceCbInfo *info = NULL;
GSList *queue = NULL, *iter;
char **arg_arr = NULL;
char **arg_ptr = argv;
int arg_num = argc;
int i;
GSList *queue, *iter;
/* Set default timeout for disconnect operation. */
if (nmc->timeout == -1)
nmc->timeout = 10;
if (argc == 0) {
if (nmc->ask) {
char *line = nmc_readline (PROMPT_INTERFACES);
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
g_free (line);
arg_ptr = arg_arr;
}
if (arg_num == 0) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
queue = device_list (nmc, argc, argv);
if (!queue)
goto error;
}
}
devices = get_devices_sorted (nmc->client);
while (arg_num > 0) {
device = NULL;
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
device = devices[i];
break;
}
}
if (device) {
if (!g_slist_find (queue, device))
queue = g_slist_prepend (queue, device);
else
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
} else {
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices found."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument */
next_arg (&arg_num, &arg_ptr);
}
g_free (devices);
if (!queue) {
g_string_printf (nmc->return_text, _("Error: no valid device provided."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
goto error;
}
queue = g_slist_reverse (queue);
info = g_slice_new0 (DeviceCbInfo);
@@ -1840,7 +1875,7 @@ do_device_disconnect (NmCli *nmc, int argc, char **argv)
G_CALLBACK (device_removed_cb), info);
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
for (iter = queue; iter; iter = g_slist_next (iter)) {
device = iter->data;
@@ -1854,7 +1889,6 @@ do_device_disconnect (NmCli *nmc, int argc, char **argv)
}
error:
g_strfreev (arg_arr);
g_slist_free (queue);
return nmc->return_value;
}
@@ -1885,71 +1919,17 @@ delete_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
static NMCResultCode
do_device_delete (NmCli *nmc, int argc, char **argv)
{
NMDevice **devices;
NMDevice *device;
DeviceCbInfo *info = NULL;
GSList *queue = NULL, *iter;
char **arg_arr = NULL;
char **arg_ptr = argv;
int arg_num = argc;
int i;
GSList *queue, *iter;
/* Set default timeout for delete operation. */
if (nmc->timeout == -1)
nmc->timeout = 10;
if (argc == 0) {
if (nmc->ask) {
char *line = nmc_readline (PROMPT_INTERFACES);
nmc_string_to_arg_array (line, NULL, FALSE, &arg_arr, &arg_num);
g_free (line);
arg_ptr = arg_arr;
}
if (arg_num == 0) {
g_string_printf (nmc->return_text, _("Error: No interface specified."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
queue = device_list (nmc, argc, argv);
if (!queue)
goto error;
}
}
devices = get_devices_sorted (nmc->client);
while (arg_num > 0) {
device = NULL;
for (i = 0; devices[i]; i++) {
if (!g_strcmp0 (nm_device_get_iface (devices[i]), *arg_ptr)) {
device = devices[i];
break;
}
}
if (device) {
if (!g_slist_find (queue, device)) {
if (nm_device_is_software (device))
queue = g_slist_prepend (queue, device);
else {
g_printerr (_("Error: Device '%s' is a hardware device. It can't be deleted.\n"),
*arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices valid."));
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
}
} else
g_printerr (_("Warning: argument '%s' is duplicated.\n"), *arg_ptr);
} else {
g_printerr (_("Error: Device '%s' not found.\n"), *arg_ptr);
g_string_printf (nmc->return_text, _("Error: not all devices found."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
}
/* Take next argument */
next_arg (&arg_num, &arg_ptr);
}
g_free (devices);
if (!queue) {
g_string_printf (nmc->return_text, _("Error: no valid device provided."));
nmc->return_value = NMC_RESULT_ERROR_NOT_FOUND;
goto error;
}
queue = g_slist_reverse (queue);
info = g_slice_new0 (DeviceCbInfo);
@@ -1961,7 +1941,7 @@ do_device_delete (NmCli *nmc, int argc, char **argv)
G_CALLBACK (device_removed_cb), info);
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
for (iter = queue; iter; iter = g_slist_next (iter)) {
device = iter->data;
@@ -1973,7 +1953,6 @@ do_device_delete (NmCli *nmc, int argc, char **argv)
}
error:
g_strfreev (arg_arr);
g_slist_free (queue);
return nmc->return_value;
}
@@ -2096,6 +2075,97 @@ error:
return nmc->return_value;
}
static void
device_state (NMDevice *device, GParamSpec *pspec, NmCli *nmc)
{
NMDeviceState state = nm_device_get_state (device);
ColorInfo color = device_state_to_color (state);
char *str = nmc_colorize (nmc, color.color, color.color_fmt, "%s: %s\n",
nm_device_get_iface (device),
nmc_device_state_to_string (state));
g_print ("%s", str);
g_free (str);
}
static void
device_ac (NMDevice *device, GParamSpec *pspec, NmCli *nmc)
{
NMActiveConnection *ac = nm_device_get_active_connection (device);
const char *id = ac ? nm_active_connection_get_id (ac) : NULL;
if (!id)
return;
g_print (_("%s: using connection '%s'\n"), nm_device_get_iface (device), id);
}
static void
device_watch (NmCli *nmc, NMDevice *device)
{
nmc->should_wait++;
g_signal_connect (device, "notify::" NM_DEVICE_STATE, G_CALLBACK (device_state), nmc);
g_signal_connect (device, "notify::" NM_DEVICE_ACTIVE_CONNECTION, G_CALLBACK (device_ac), nmc);
}
static void
device_unwatch (NmCli *nmc, NMDevice *device)
{
g_signal_handlers_disconnect_by_func (device, device_state, nmc);
if (g_signal_handlers_disconnect_by_func (device, device_ac, nmc))
nmc->should_wait--;
/* Terminate if all the watched devices disappeared. */
if (!nmc->should_wait)
quit ();
}
static void
device_added (NMClient *client, NMDevice *device, NmCli *nmc)
{
g_print (_("%s: device created\n"), nm_device_get_iface (device));
device_watch (nmc, NM_DEVICE (device));
}
static void
device_removed (NMClient *client, NMDevice *device, NmCli *nmc)
{
g_print (_("%s: device removed\n"), nm_device_get_iface (device));
device_unwatch (nmc, device);
}
static NMCResultCode
do_device_monitor (NmCli *nmc, int argc, char **argv)
{
if (argc == 0) {
/* No devices specified. Monitor all. */
const GPtrArray *devices = nm_client_get_devices (nmc->client);
int i;
for (i = 0; i < devices->len; i++)
device_watch (nmc, g_ptr_array_index (devices, i));
/* We'll watch the device additions too, never exit. */
nmc->should_wait++;
g_signal_connect (nmc->client, NM_CLIENT_DEVICE_ADDED, G_CALLBACK (device_added), nmc);
} else {
/* Monitor just the specified devices. */
GSList *queue = device_list (nmc, argc, argv);
GSList *iter;
if (!queue)
return nmc->return_value;
for (iter = queue; iter; iter = g_slist_next (iter))
device_watch (nmc, NM_DEVICE (iter->data));
g_slist_free (queue);
}
g_signal_connect (nmc->client, NM_CLIENT_DEVICE_REMOVED, G_CALLBACK (device_removed), nmc);
return NMC_RESULT_SUCCESS;
}
static void
show_access_point_info (NMDevice *device, NmCli *nmc)
{
@@ -2726,7 +2796,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
* the user doesn't want to wait, in order to give NM time to check our
* permissions. */
nmc->nowait_flag = (nmc->timeout == 0);
nmc->should_wait = TRUE;
nmc->should_wait++;
info = g_malloc0 (sizeof (AddAndActivateInfo));
info->nmc = nmc;
@@ -3116,8 +3186,6 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
const char *ssid;
int i;
nmc->should_wait = TRUE;
ssids = g_ptr_array_new ();
/* Get the parameters */
@@ -3185,7 +3253,7 @@ do_device_wifi_rescan (NmCli *nmc, int argc, char **argv)
g_ptr_array_free (ssids, FALSE);
return nmc->return_value;
error:
nmc->should_wait = FALSE;
nmc->should_wait++;
g_ptr_array_free (ssids, FALSE);
return nmc->return_value;
}
@@ -3546,6 +3614,13 @@ do_devices (NmCli *nmc, int argc, char **argv)
}
nmc->return_value = do_device_set (nmc, argc-1, argv+1);
}
else if (matches (*argv, "monitor") == 0) {
if (nmc_arg_is_help (*(argv+1))) {
usage_device_monitor ();
goto usage_exit;
}
nmc->return_value = do_device_monitor (nmc, argc-1, argv+1);
}
else if (matches (*argv, "wifi") == 0) {
if (nmc_arg_is_help (*(argv+1))) {
usage_device_wifi ();
@@ -3582,3 +3657,9 @@ opt_error:
g_error_free (error);
return nmc->return_value;
}
void
monitor_devices (NmCli *nmc)
{
do_device_monitor (nmc, 0, NULL);
}

View File

@@ -24,4 +24,6 @@
NMCResultCode do_devices (NmCli *nmc, int argc, char **argv);
void monitor_devices (NmCli *nmc);
#endif /* NMC_DEVICES_H */

View File

@@ -27,6 +27,9 @@
#include "utils.h"
#include "general.h"
#include "devices.h"
#include "connections.h"
/* Available fields for 'general status' */
static NmcOutputField nmc_fields_nm_status[] = {
{"RUNNING", N_("RUNNING")}, /* 0 */
@@ -207,6 +210,15 @@ usage_radio_wwan (void)
"Get status of mobile broadband radio switch, or turn it on/off.\n\n"));
}
static void
usage_monitor (void)
{
g_printerr (_("Usage: nmcli monitor\n"
"\n"
"Monitor NetworkManager changes.\n"
"Prints a line whenever a change occurs in NetworkManager\n\n"));
}
/* quit main loop */
static void
quit (void)
@@ -619,7 +631,7 @@ do_general (NmCli *nmc, int argc, char **argv)
if (next_arg (&argc, &argv) == 0)
g_print ("Warning: ignoring extra garbage after '%s' hostname\n", hostname);
nmc->should_wait = TRUE;
nmc->should_wait++;
nmc->get_client (nmc); /* create NMClient */
nm_client_save_hostname_async (nmc->client, hostname, NULL, save_hostname_cb, nmc);
}
@@ -889,3 +901,88 @@ finish:
return nmc->return_value;
}
static void
client_hostname (NMClient *client, GParamSpec *param, NmCli *nmc)
{
const char *hostname;
g_object_get (client, NM_CLIENT_HOSTNAME, &hostname, NULL);
g_print (_("Hostname set to '%s'\n"), hostname);
}
static void
client_primary_connection (NMClient *client, GParamSpec *param, NmCli *nmc)
{
NMConnection *primary;
const char *id;
g_object_get (client, NM_CLIENT_PRIMARY_CONNECTION, &primary, NULL);
if (primary) {
id = nm_connection_get_id (primary);
if (!id)
id = nm_connection_get_uuid (primary);
g_print (_("'%s' is now the primary connection\n"), id);
} else {
g_print (_("There's no primary connection\n"));
}
}
static void
client_connectivity (NMClient *client, GParamSpec *param, NmCli *nmc)
{
NMConnectivityState connectivity;
char *str;
g_object_get (client, NM_CLIENT_CONNECTIVITY, &connectivity, NULL);
str = nmc_colorize (nmc, 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);
}
static void
client_state (NMClient *client, GParamSpec *param, NmCli *nmc)
{
NMState state;
char *str;
g_object_get (client, NM_CLIENT_STATE, &state, NULL);
str = nmc_colorize (nmc, 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);
g_free (str);
}
NMCResultCode
do_monitor (NmCli *nmc, int argc, char **argv)
{
if (argc > 0) {
if (!nmc_arg_is_help (*argv)) {
g_string_printf (nmc->return_text, _("Error: 'monitor' command '%s' is not valid."), *argv);
nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
}
usage_monitor ();
return nmc->return_value;
}
nmc->get_client (nmc); /* create NMClient */
g_signal_connect (nmc->client, "notify::" NM_CLIENT_HOSTNAME,
G_CALLBACK (client_hostname), nmc);
g_signal_connect (nmc->client, "notify::" NM_CLIENT_PRIMARY_CONNECTION,
G_CALLBACK (client_primary_connection), nmc);
g_signal_connect (nmc->client, "notify::" NM_CLIENT_CONNECTIVITY,
G_CALLBACK (client_connectivity), nmc);
g_signal_connect (nmc->client, "notify::" NM_CLIENT_STATE,
G_CALLBACK (client_state), nmc);
nmc->should_wait++;
monitor_devices (nmc);
monitor_connections (nmc);
return NMC_RESULT_SUCCESS;
}

View File

@@ -25,5 +25,6 @@
NMCResultCode do_general (NmCli *nmc, int argc, char **argv);
NMCResultCode do_networking (NmCli *nmc, int argc, char **argv);
NMCResultCode do_radio (NmCli *nmc, int argc, char **argv);
NMCResultCode do_monitor (NmCli *nmc, int argc, char **argv);
#endif /* NMC_GENERAL_H */

View File

@@ -798,7 +798,7 @@ _nmcli()
# (if the current word starts with a dash) or the OBJECT list
# otherwise.
if [[ "${words[0]:0:1}" != '-' ]]; then
OPTIONS=(help general networking radio connection device agent)
OPTIONS=(help general networking radio connection device agent monitor)
elif [[ "${words[0]:1:1}" == '-' || "${words[0]}" == "-" ]]; then
OPTIONS=("${LONG_OPTIONS[@]/#/--}")
else
@@ -870,7 +870,7 @@ _nmcli()
;;
c|co|con|conn|conne|connec|connect|connecti|connectio|connection)
if [[ ${#words[@]} -eq 2 ]]; then
_nmcli_compl_COMMAND "$command" show up down add modify clone edit delete reload load
_nmcli_compl_COMMAND "$command" show up down add modify clone edit delete monitor reload load
elif [[ ${#words[@]} -gt 2 ]]; then
case "$command" in
s|sh|sho|show)
@@ -1280,7 +1280,8 @@ _nmcli()
fi
;;
de|del|dele|delet|delete)
de|del|dele|delet|delete| \
m|mo|mon|moni|monit|monito|monitor)
if [[ ${#words[@]} -eq 3 ]]; then
_nmcli_compl_COMMAND_nl "${words[2]}" "$(printf "id\nuuid\npath\n%s" "$(_nmcli_con_show NAME)")"
elif [[ ${#words[@]} -gt 3 ]]; then
@@ -1319,7 +1320,7 @@ _nmcli()
;;
d|de|dev|devi|devic|device)
if [[ ${#words[@]} -eq 2 ]]; then
_nmcli_compl_COMMAND "$command" status show connect disconnect delete wifi set lldp
_nmcli_compl_COMMAND "$command" status show connect disconnect delete monitor wifi set lldp
elif [[ ${#words[@]} -gt 2 ]]; then
case "$command" in
s|st|sta|stat|statu|status)
@@ -1334,7 +1335,8 @@ _nmcli()
fi
;;
d|di|dis|disc|disco|discon|disconn|disconne|disconnec|disconnect| \
de|del|dele|delet|delete)
de|del|dele|delet|delete| \
m|mo|mon|moni|monit|monito|monitor)
if [[ ${#words[@]} -ge 3 ]]; then
_nmcli_compl_COMMAND_nl "${words[2]}" "$(_nmcli_dev_status DEVICE)"
fi
@@ -1408,6 +1410,8 @@ _nmcli()
_nmcli_compl_COMMAND "$command" secret polkit all
fi
;;
m|mo|mon|moni|monit|monito|monitor)
;;
esac
return 0

View File

@@ -103,6 +103,7 @@ usage (const char *prog_name)
" c[onnection] NetworkManager's connections\n"
" d[evice] devices managed by NetworkManager\n"
" a[gent] NetworkManager secret agent or polkit agent\n"
" m[monitor] monitor NetworkManager changes\n"
"\n"),
prog_name);
}
@@ -119,6 +120,7 @@ static const struct cmd {
NMCResultCode (*func) (NmCli *nmc, int argc, char **argv);
} nmcli_cmds[] = {
{ "general", do_general },
{ "monitor", do_monitor },
{ "networking", do_networking },
{ "radio", do_radio },
{ "connection", do_connections },
@@ -532,7 +534,7 @@ nmc_init (NmCli *nmc)
nmc->pwds_hash = NULL;
nmc->pk_listener = NULL;
nmc->should_wait = FALSE;
nmc->should_wait = 0;
nmc->nowait_flag = TRUE;
nmc->print_output = NMC_PRINT_NORMAL;
nmc->multiline_output = FALSE;

View File

@@ -144,7 +144,7 @@ typedef struct _NmCli {
GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */
NMPolkitListener *pk_listener ; /* polkit agent listener */
gboolean should_wait; /* Indication that nmcli should not end yet */
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 */

View File

@@ -356,8 +356,20 @@ nmc_term_format_sequence (NmcTermFormat format)
}
}
static gboolean
use_colors (NmCli *nmc)
{
if (nmc == NULL)
return FALSE;
if (nmc->use_colors == NMC_USE_COLOR_AUTO)
nmc->use_colors = isatty (fileno (stdout)) ? NMC_USE_COLOR_YES : NMC_USE_COLOR_NO;
return nmc->use_colors == NMC_USE_COLOR_YES;
}
char *
nmc_colorize (NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
nmc_colorize (NmCli *nmc, NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
{
va_list args;
char *str, *colored;
@@ -368,6 +380,9 @@ nmc_colorize (NmcTermColor color, NmcTermFormat format, const char *fmt, ...)
str = g_strdup_vprintf (fmt, args);
va_end (args);
if (!use_colors (nmc))
return str;
ansi_color = nmc_term_color_sequence (color);
ansi_fmt = nmc_term_format_sequence (format);
color_end = *ansi_color ? end_seq : "";
@@ -1047,7 +1062,7 @@ nmc_empty_output_fields (NmCli *nmc)
}
static char *
colorize_string (gboolean colorize,
colorize_string (NmCli *nmc,
NmcTermColor color,
NmcTermFormat color_fmt,
const char *str,
@@ -1055,9 +1070,9 @@ colorize_string (gboolean colorize,
{
char *out;
if ( colorize
if ( use_colors (nmc)
&& (color != NMC_TERM_COLOR_NORMAL || color_fmt != NMC_TERM_FORMAT_NORMAL)) {
out = nmc_colorize (color, color_fmt, str);
out = nmc_colorize (nmc, color, color_fmt, str);
*dealloc = TRUE;
} else {
out = (char *) str;
@@ -1067,11 +1082,11 @@ colorize_string (gboolean colorize,
}
static char *
get_value_to_print (NmcOutputField *field,
get_value_to_print (NmCli *nmc,
NmcOutputField *field,
gboolean field_name,
const char *not_set_str,
gboolean *dealloc,
gboolean colorize)
gboolean *dealloc)
{
gboolean is_array = field->value_is_array;
char *value, *out;
@@ -1087,7 +1102,7 @@ get_value_to_print (NmcOutputField *field,
free_value = field->value && is_array && !field_name;
/* colorize the value */
out = colorize_string (colorize, field->color, field->color_fmt, value, &free_out);
out = colorize_string (nmc, field->color, field->color_fmt, value, &free_out);
if (free_out) {
if (free_value)
g_free (value);
@@ -1125,7 +1140,6 @@ 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
@@ -1133,11 +1147,6 @@ 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 };
@@ -1178,7 +1187,7 @@ 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 (colorize, field_values[idx].color, field_values[idx].color_fmt,
print_val = colorize_string (nmc, 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 : "",
@@ -1199,7 +1208,7 @@ print_required_fields (NmCli *nmc, const NmcOutputField field_values[])
char *print_val;
val = val ? val : not_set_str;
print_val = colorize_string (colorize, field_values[idx].color, field_values[idx].color_fmt,
print_val = colorize_string (nmc, field_values[idx].color, field_values[idx].color_fmt,
val, &free_print_val);
tmp = g_strdup_printf ("%s%s%s:",
section_prefix ? hdr_name : "",
@@ -1228,8 +1237,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, colorize);
char *value = get_value_to_print (nmc, (NmcOutputField *) field_values+idx, field_names,
not_set_str, &dealloc);
if (terse) {
if (escape) {
@@ -1327,7 +1336,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, FALSE);
value = get_value_to_print (NULL, row+i, field_names, "--", &dealloc);
len = nmc_string_screen_width (value, NULL);
max_width = len > max_width ? len : max_width;
if (dealloc)

View File

@@ -76,7 +76,7 @@ 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 (NmcTermColor color, NmcTermFormat format, const char * fmt, ...);
char *nmc_colorize (NmCli *nmc, 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);

View File

@@ -1562,14 +1562,16 @@ nm_device_get_product (NMDevice *device)
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->product) {
if (!priv->product)
priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_MODEL_FROM_DATABASE");
if (!priv->product) {
/* Sometimes ID_PRODUCT_FROM_DATABASE is used? */
if (!priv->product)
priv->product = _get_udev_property (device, "ID_MODEL_ENC", "ID_PRODUCT_FROM_DATABASE");
}
_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_PRODUCT);
}
if (!priv->product)
priv->product = g_strdup ("");
return priv->product;
}
@@ -1590,10 +1592,13 @@ nm_device_get_vendor (NMDevice *device)
g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
priv = NM_DEVICE_GET_PRIVATE (device);
if (!priv->vendor) {
if (!priv->vendor)
priv->vendor = _get_udev_property (device, "ID_VENDOR_ENC", "ID_VENDOR_FROM_DATABASE");
_nm_object_queue_notify (NM_OBJECT (device), NM_DEVICE_VENDOR);
}
if (!priv->vendor)
priv->vendor = g_strdup ("");
return priv->vendor;
}

View File

@@ -1010,7 +1010,9 @@ properties_changed (GDBusProxy *proxy,
G_STMT_START { \
if (g_variant_is_of_type (value, vtype)) { \
ctype *param = (ctype *) field; \
*param = getter (value); \
ctype newval = getter (value); \
different = *param != newval; \
*param = newval; \
} else { \
success = FALSE; \
goto done; \
@@ -1024,20 +1026,29 @@ demarshal_generic (NMObject *object,
gpointer field)
{
gboolean success = TRUE;
gboolean different = FALSE;
if (pspec->value_type == G_TYPE_STRING) {
if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
char **param = (char **) field;
const char *newval = g_variant_get_string (value, NULL);
different = !!g_strcmp0 (*param, newval);
if (different) {
g_free (*param);
*param = g_variant_dup_string (value, NULL);
*param = g_strdup (newval);
}
} else if (g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH)) {
char **param = (char **) field;
g_free (*param);
*param = g_variant_dup_string (value, NULL);
const char *newval = g_variant_get_string (value, NULL);
/* Handle "NULL" object paths */
if (g_strcmp0 (*param, "/") == 0) {
if (g_strcmp0 (newval, "/") == 0)
newval = NULL;
different = !!g_strcmp0 (*param, newval);
if (different) {
g_free (*param);
*param = NULL;
*param = g_strdup (newval);
}
} else {
success = FALSE;
@@ -1045,50 +1056,78 @@ demarshal_generic (NMObject *object,
}
} else if (pspec->value_type == G_TYPE_STRV) {
char ***param = (char ***)field;
if (*param)
const char **newval;
gsize i;
newval = g_variant_get_strv (value, NULL);
if (!*param)
different = TRUE;
else {
if (!_nm_utils_strv_equal ((char **) newval, *param)) {
different = TRUE;
g_strfreev (*param);
*param = g_variant_dup_strv (value, NULL);
}
}
if (different) {
for (i = 0; newval[i]; i++)
newval[i] = g_strdup (newval[i]);
*param = (char **) newval;
} else
g_free (newval);
} else if (pspec->value_type == G_TYPE_BYTES) {
GBytes **param = (GBytes **)field;
gconstpointer val;
gsize length;
gconstpointer val, old_val = NULL;
gsize length, old_length = 0;
val = g_variant_get_fixed_array (value, &length, 1);
if (*param)
old_val = g_bytes_get_data (*param, &old_length);
different = old_length != length
|| ( length > 0
&& memcmp (old_val, val, length) != 0);
if (different) {
if (*param)
g_bytes_unref (*param);
val = g_variant_get_fixed_array (value, &length, 1);
if (length)
*param = g_bytes_new (val, length);
else
*param = NULL;
*param = length > 0 ? g_bytes_new (val, length) : NULL;
}
} else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
int *param = (int *) field;
int newval = 0;
if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
*param = g_variant_get_int32 (value);
newval = g_variant_get_int32 (value);
else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
*param = g_variant_get_uint32 (value);
newval = g_variant_get_uint32 (value);
else {
success = FALSE;
goto done;
}
different = *param != newval;
*param = newval;
} else if (G_IS_PARAM_SPEC_FLAGS (pspec)) {
guint *param = (guint *) field;
guint newval = 0;
if (g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
*param = g_variant_get_int32 (value);
newval = g_variant_get_int32 (value);
else if (g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
*param = g_variant_get_uint32 (value);
newval = g_variant_get_uint32 (value);
else {
success = FALSE;
goto done;
}
different = *param != newval;
*param = newval;
} else if (pspec->value_type == G_TYPE_BOOLEAN)
HANDLE_TYPE (G_VARIANT_TYPE_BOOLEAN, gboolean, g_variant_get_boolean);
else if (pspec->value_type == G_TYPE_UCHAR)
HANDLE_TYPE (G_VARIANT_TYPE_BYTE, guchar, g_variant_get_byte);
else if (pspec->value_type == G_TYPE_DOUBLE)
else if (pspec->value_type == G_TYPE_DOUBLE) {
NM_PRAGMA_WARNING_DISABLE("-Wfloat-equal")
HANDLE_TYPE (G_VARIANT_TYPE_DOUBLE, gdouble, g_variant_get_double);
else if (pspec->value_type == G_TYPE_INT)
NM_PRAGMA_WARNING_REENABLE
} else if (pspec->value_type == G_TYPE_INT)
HANDLE_TYPE (G_VARIANT_TYPE_INT32, gint, g_variant_get_int32);
else if (pspec->value_type == G_TYPE_UINT)
HANDLE_TYPE (G_VARIANT_TYPE_UINT32, guint, g_variant_get_uint32);
@@ -1111,6 +1150,7 @@ demarshal_generic (NMObject *object,
done:
if (success) {
if (different)
_nm_object_queue_notify (object, pspec->name);
} else {
dbgmsg ("%s: %s:%s (type %s) couldn't be set from D-Bus type %s.",

View File

@@ -33,7 +33,7 @@ nmcli \- command\(hyline tool for controlling NetworkManager
.sp
.IR OBJECT " := { "
.BR general " | " networking " | " radio " | " connection " | " device " | " agent
.BR general " | " networking " | " radio " | " connection " | " device " | " agent " | " monitor
.RI " }"
.sp
@@ -259,6 +259,16 @@ are supplied, mobile broadband status is printed; \fIon\fP enables mobile broadb
Show or set all previously mentioned radio switches at the same time.
.RE
.TP
.B monitor \- monitor NetworkManager
.br
Use this object to observe NetworkManager activity. Watches for changes
in connectivity state, devices or connection profiles.
.br
See also \fImonitor\fP command of \fIconnection\fP or \fIdevice\fP object
to watch for changes in certain objects or object classes.
.RE
.TP
.B connection \- start, stop, and manage network connections
.sp
@@ -278,7 +288,7 @@ be saved as two connections which both apply to eth0, one for DHCP (called
connected to the DHCP-enabled network the user would run "nmcli con up default"
, and when connected to the static network the user would run "nmcli con up testing".
.TP
.SS \fICOMMAND\fP := { show | up | down | add | edit | modify | delete | reload | load }
.SS \fICOMMAND\fP := { show | up | down | add | edit | modify | delete | monitor | reload | load }
.sp
.RS
.TP
@@ -779,6 +789,19 @@ See \fBconnection show\fP above for the description of the <ID>-specifying keywo
.br
If '--wait' option is not specified, the default timeout will be 10 seconds.
.TP
.B monitor [ id | uuid | path ] <ID> ...
.br
Monitor connection profile activity. This command prints a line whenever the
specified connection changes. The connection to be monitored is identified by
its name, UUID or D-Bus path. If <ID> is ambiguous, a keyword \fIid\fP,
\fIuuid\fP or \fIpath\fP can be used.
.br
See \fBconnection show\fP above for the description of the <ID>-specifying keywords.
.br
Monitors all connection profiles in case none is specified. The command terminates
when all monitored connections disappear. If you want to monitor connection creation
consider using the global monitor with \fInmcli monitor\fP command.
.TP
.B reload
.br
Reload all connection files from disk. \fINetworkManager\fP does not monitor
@@ -799,7 +822,7 @@ of its latest state.
.B device - show and manage network interfaces
.br
.TP
.SS \fICOMMAND\fP := { status | show | set | connect | disconnect | delete | wifi | lldp }
.SS \fICOMMAND\fP := { status | show | set | connect | disconnect | delete | monitor | wifi | lldp }
.sp
.RS
.TP
@@ -843,6 +866,15 @@ Hardware devices (like Ethernet) cannot be deleted by the command.
.br
If '--wait' option is not specified, the default timeout will be 10 seconds.
.TP
.B monitor [<ifname>] ...
.br
Monitor device activity. This command prints a line whenever the specified devices
change state.
.br
Monitors all devices in case no interface is specified. The monitor terminates when
all specified devices disappear. If you want to monitor device addition consider
using the global monitor with \fInmcli monitor\fP command.
.TP
.B wifi [list [ifname <ifname>] [bssid <BSSID>]]
.br
List available Wi\(hyFi access points. The \fIifname\fP and \fIbssid\fP options