summary refs log tree commit diff
path: root/clients/cli
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2019-02-26 19:01:41 +0100
committerMichael Biebl <biebl@debian.org>2019-02-26 19:01:41 +0100
commit964ae8cc391520440cf5aa13e2b9cc34850ea6c2 (patch)
tree50da9ecaee7fbb612ec18f9e24f7dec215bf7861 /clients/cli
parent3626b425d1bc017fdc6f1ea0cfd329d1e1681641 (diff)
New upstream version 1.14.6 upstream/1.14.6
Diffstat (limited to 'clients/cli')
-rw-r--r--clients/cli/connections.c58
-rw-r--r--clients/cli/devices.c155
-rw-r--r--clients/cli/utils.c2
3 files changed, 143 insertions, 72 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index bcd257ac..8a10691e 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -6534,6 +6534,12 @@ static gboolean nmc_editor_cb_called;
 static GError *nmc_editor_error;
 static MonitorACInfo *nmc_editor_monitor_ac;
 
+static void
+editor_connection_changed_cb (NMConnection *connection, gboolean *changed)
+{
+	*changed = TRUE;
+}
+
 /*
  * Store 'error' to shared 'nmc_editor_error' and monitoring info to
  * 'nmc_editor_monitor_ac' and signal the condition so that
@@ -6579,8 +6585,8 @@ static gboolean
 progress_activation_editor_cb (gpointer user_data)
 {
 	MonitorACInfo *info = (MonitorACInfo *) user_data;
-	gs_unref_object NMDevice *device = info->device;
-	gs_unref_object NMActiveConnection *ac = info->ac;
+	NMDevice *device = info->device;
+	NMActiveConnection *ac = info->ac;
 	NMActiveConnectionState ac_state;
 	NMDeviceState dev_state;
 
@@ -6613,11 +6619,13 @@ progress_activation_editor_cb (gpointer user_data)
 		                               nm_object_get_path (NM_OBJECT (connection)));
 	}
 
-	return TRUE;
+	return G_SOURCE_CONTINUE;
 
 finish:
+	nm_g_object_unref (device);
+	nm_g_object_unref (ac);
 	info->monitor_id = 0;
-	return FALSE;
+	return G_SOURCE_REMOVE;
 }
 
 static void
@@ -7128,6 +7136,16 @@ menu_switch_to_level1 (const NmcConfig *nmc_config,
 }
 
 static gboolean
+editor_save_timeout (gpointer user_data)
+{
+	gboolean *timeout = user_data;
+
+	*timeout = TRUE;
+
+	return G_SOURCE_REMOVE;
+}
+
+static gboolean
 editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
 {
 	gs_unref_object NMRemoteConnection *rem_con = NULL;
@@ -7646,6 +7664,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
 			/* Save the connection */
 			if (nm_connection_verify (connection, &err1)) {
 				gboolean persistent = TRUE;
+				gboolean connection_changed;
+				nm_auto_unref_gsource GSource *source = NULL;
+				gboolean timeout = FALSE;
+				gulong handler_id = 0;
 
 				/* parse argument */
 				if (cmd_arg) {
@@ -7674,23 +7696,44 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
 					                    connection,
 					                    add_connection_editor_cb,
 					                    info);
+					connection_changed = TRUE;
 				} else {
 					/* Save/update already saved (existing) connection */
 					nm_connection_replace_settings_from_connection (NM_CONNECTION (rem_con),
 					                                                connection);
 					update_connection (persistent, rem_con, update_connection_editor_cb, NULL);
+
+					handler_id = g_signal_connect (rem_con,
+					                               NM_CONNECTION_CHANGED,
+					                               G_CALLBACK (editor_connection_changed_cb),
+					                               &connection_changed);
+					connection_changed = FALSE;
 				}
 
-				//FIXME: add also a timeout for cases the callback is not called
-				while (!nmc_editor_cb_called)
+				source = g_timeout_source_new (10 * NM_UTILS_MSEC_PER_SECOND);
+				g_source_set_callback (source, editor_save_timeout, &timeout, NULL);
+				g_source_attach (source, g_main_loop_get_context (loop));
+
+				while (!nmc_editor_cb_called && !timeout)
 					g_main_context_iteration (NULL, TRUE);
 
+				while (!connection_changed && !timeout)
+					g_main_context_iteration (NULL, TRUE);
+
+				if (handler_id)
+					g_signal_handler_disconnect (rem_con, handler_id);
+				g_source_destroy (source);
+
 				if (nmc_editor_error) {
 					g_print (_("Error: Failed to save '%s' (%s) connection: %s\n"),
 					         nm_connection_get_id (connection),
 					         nm_connection_get_uuid (connection),
 					         nmc_editor_error->message);
 					g_error_free (nmc_editor_error);
+				} else if (timeout) {
+					g_print (_("Error: Timeout saving '%s' (%s) connection\n"),
+					         nm_connection_get_id (connection),
+					         nm_connection_get_uuid (connection));
 				} else {
 					g_print (!rem_con ?
 					         _("Connection '%s' (%s) successfully saved.\n") :
@@ -7713,9 +7756,10 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
 						if (menu_ctx.curr_setting)
 							s_name = g_strdup (nm_setting_get_name (menu_ctx.curr_setting));
 
-						/* Update settings in the local connection */
+						/* Update settings and secrets in the local connection */
 						nm_connection_replace_settings_from_connection (connection,
 						                                                NM_CONNECTION (con_tmp));
+						update_secrets_in_connection (con_tmp, connection);
 
 						/* Also update setting for menu context and TAB-completion */
 						menu_ctx.curr_setting = s_name ? nm_connection_get_setting_by_name (connection, s_name) : NULL;
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index 029ca671..5aaf4ef8 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -2094,6 +2094,7 @@ typedef struct {
 	GSList *queue;
 	guint timeout_id;
 	gboolean cmd_disconnect;
+	GCancellable *cancellable;
 } DeviceCbInfo;
 
 static void device_cb_info_finish (DeviceCbInfo *info, NMDevice *device);
@@ -2166,7 +2167,10 @@ device_cb_info_finish (DeviceCbInfo *info, NMDevice *device)
 
 	if (info->timeout_id)
 		g_source_remove (info->timeout_id);
+
 	g_signal_handlers_disconnect_by_func (info->nmc->client, device_removed_cb, info);
+	nm_clear_g_cancellable (&info->cancellable);
+
 	g_slice_free (DeviceCbInfo, info);
 	quit ();
 }
@@ -2343,11 +2347,14 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 {
 	NMDevice *device = NM_DEVICE (object);
 	DeviceCbInfo *info = (DeviceCbInfo *) user_data;
-	NmCli *nmc = info->nmc;
+	NmCli *nmc;
 	NMDeviceState state;
 	GError *error = NULL;
 
 	if (!nm_device_disconnect_finish (device, result, &error)) {
+		if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+			return;
+		nmc = info->nmc;
 		g_string_printf (nmc->return_text, _("Error: not all devices disconnected."));
 		g_printerr (_("Error: Device '%s' (%s) disconnecting failed: %s\n"),
 		            nm_device_get_iface (device),
@@ -2357,6 +2364,7 @@ disconnect_device_cb (GObject *object, GAsyncResult *result, gpointer user_data)
 		nmc->return_value = NMC_RESULT_ERROR_DEV_DISCONNECT;
 		device_cb_info_finish (info, device);
 	} else {
+		nmc = info->nmc;
 		state = nm_device_get_state (device);
 		if (nmc->nowait_flag || state <= NM_DEVICE_STATE_DISCONNECTED) {
 			/* Don't want to wait or device already disconnected */
@@ -2393,6 +2401,7 @@ do_devices_disconnect (NmCli *nmc, int argc, char **argv)
 	info = g_slice_new0 (DeviceCbInfo);
 	info->nmc = nmc;
 	info->cmd_disconnect = TRUE;
+	info->cancellable = g_cancellable_new ();
 	if (nmc->timeout > 0)
 		info->timeout_id = g_timeout_add_seconds (nmc->timeout, device_op_timeout_cb, info);
 
@@ -2410,7 +2419,7 @@ do_devices_disconnect (NmCli *nmc, int argc, char **argv)
 		                  G_CALLBACK (disconnect_state_cb), info);
 
 		/* Now disconnect the device */
-		nm_device_disconnect_async (device, NULL, disconnect_device_cb, info);
+		nm_device_disconnect_async (device, info->cancellable, disconnect_device_cb, info);
 	}
 
 out:
@@ -2795,7 +2804,7 @@ show_access_point_info (NMDeviceWifi *wifi, NmCli *nmc, NmcOutputData *out)
 
 		aps = sort_access_points (nm_device_wifi_get_access_points (wifi));
 		g_ptr_array_foreach (aps, fill_output_access_point, &info);
-		g_ptr_array_free (aps, FALSE);
+		g_ptr_array_free (aps, TRUE);
 	}
 
 	print_data_prepare_width (out->output_data);
@@ -2870,28 +2879,38 @@ wifi_print_aps (NMDeviceWifi *wifi,
 
 typedef struct {
 	NmCli *nmc;
-	NMDeviceWifi *wifi;
-	const NMMetaAbstractInfo *const*tmpl;
-
+	NMDevice **devices;
+	const NMMetaAbstractInfo *const *tmpl;
 	const char *bssid_user;
+	GArray *out_indices;
+} ScanInfo;
+
+typedef struct {
+	ScanInfo *scan_info;
+	NMDeviceWifi *wifi;
 	gulong last_scan_id;
 	guint  timeout_id;
 	GCancellable *scan_cancellable;
-	GArray *out_indices;
 } WifiListData;
 
 static void
 wifi_list_finish (WifiListData *data)
 {
-	NmCli *nmc = data->nmc;
-
-	wifi_print_aps (data->wifi, data->nmc, data->out_indices,
-	                data->tmpl, data->bssid_user);
+	ScanInfo *info = data->scan_info;
+	NmCli *nmc = info->nmc;
+	guint i;
 
-	if (--nmc->should_wait == 0) {
+	if (--info->nmc->should_wait == 0) {
+		for (i = 0; info->devices[i]; i++) {
+			wifi_print_aps (NM_DEVICE_WIFI (info->devices[i]),
+			                info->nmc,
+			                info->out_indices,
+			                info->tmpl,
+			                info->bssid_user);
+		}
 		if (nmc->return_value == NMC_RESULT_ERROR_NOT_FOUND) {
 			g_string_printf (nmc->return_text, _("Error: Access point with bssid '%s' not found."),
-			                 data->bssid_user);
+			                 data->scan_info->bssid_user);
 		}
 		g_main_loop_quit (loop);
 	}
@@ -2899,9 +2918,15 @@ wifi_list_finish (WifiListData *data)
 	g_signal_handler_disconnect (data->wifi, data->last_scan_id);
 	nm_clear_g_source (&data->timeout_id);
 	nm_clear_g_cancellable (&data->scan_cancellable);
-	g_array_unref (data->out_indices);
-	g_object_unref (data->wifi);
 	g_slice_free (WifiListData, data);
+
+	if (info->nmc->should_wait == 0) {
+		for (i = 0; info->devices[i]; i++)
+			g_object_unref (info->devices[i]);
+		g_free (info->devices);
+		g_array_unref (info->out_indices);
+		g_free (info);
+	}
 }
 
 static void
@@ -2946,49 +2971,6 @@ wifi_list_scan_timeout (gpointer user_data)
 }
 
 static void
-wifi_list_aps (NMDeviceWifi *wifi,
-               NmCli *nmc,
-               GArray *out_indices,
-               const NMMetaAbstractInfo *const*tmpl,
-               const char *bssid_user,
-               gint64 rescan_cutoff)
-{
-	gboolean needs_rescan;
-	WifiListData *data;
-
-	needs_rescan = rescan_cutoff < 0 || (rescan_cutoff > 0 && nm_device_wifi_get_last_scan (wifi) < rescan_cutoff);
-
-	/* FIXME: nmcli should either
-	 *  - don't request any new scan for any device and print the full AP list right
-	 *    away.
-	 *  - or, when requesting a scan on one or more devices, don't print the result
-	 *    before all requests complete.
-	 *
-	 *  Otherwise:
-	 *    - the printed output is not self consistent. E.g. it will print the result
-	 *      on one device at a certain time, while printing the result for another
-	 *      device at a later point in time.
-	 *    - the order in which we print the AP list per-device, is unstable. */
-	if (needs_rescan) {
-		data = g_slice_new0 (WifiListData);
-		data->nmc = nmc;
-		data->wifi = g_object_ref (wifi);
-		data->tmpl = tmpl;
-		data->out_indices = g_array_ref (out_indices);;
-		data->bssid_user = bssid_user;
-		data->last_scan_id = g_signal_connect (wifi, "notify::" NM_DEVICE_WIFI_LAST_SCAN,
-		                                       G_CALLBACK (wifi_last_scan_updated), data);
-		data->scan_cancellable = g_cancellable_new ();
-		data->timeout_id = g_timeout_add_seconds (15, wifi_list_scan_timeout, data);
-		nm_device_wifi_request_scan_async (wifi, data->scan_cancellable, wifi_list_rescan_cb, data);
-
-		nmc->should_wait++;
-	} else {
-		wifi_print_aps (wifi, nmc, out_indices, tmpl, bssid_user);
-	}
-}
-
-static void
 complete_aps (NMDevice **devices, const char *ifname,
               const char *bssid_prefix, const char *ssid_prefix)
 {
@@ -3017,12 +2999,15 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 	const char *bssid_user = NULL;
 	const char *rescan = NULL;
 	gs_free NMDevice **devices = NULL;
-	guint i;
 	const char *fields_str = NULL;
 	const NMMetaAbstractInfo *const*tmpl;
 	gs_unref_array GArray *out_indices = NULL;
 	int option;
 	guint64 rescan_cutoff;
+	NMDeviceWifi *wifi;
+	ScanInfo *scan_info = NULL;
+	WifiListData *data;
+	guint i, j;
 
 	devices = nmc_get_devices_sorted (nmc->client);
 
@@ -3110,7 +3095,8 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 		}
 
 		if (NM_IS_DEVICE_WIFI (device)) {
-			wifi_list_aps (NM_DEVICE_WIFI (device), nmc, out_indices, tmpl, bssid_user, rescan_cutoff);
+			devices[0] = device;
+			devices[1] = NULL;
 		} else {
 			if (   nm_device_get_device_type (device) == NM_DEVICE_TYPE_GENERIC
 			    && g_strcmp0 (nm_device_get_type_description (device), "wifi") == 0) {
@@ -3124,13 +3110,52 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
 			}
 			return NMC_RESULT_ERROR_UNKNOWN;
 		}
+	}
+
+	/* Filter out non-wifi devices */
+	for (i = 0, j = 0; devices[i]; i++) {
+		if (NM_IS_DEVICE_WIFI (devices[i]))
+			devices[j++] = devices[i];
+	}
+	devices[j] = NULL;
+
+	/* Start a new scan for devices that need it */
+	for (i = 0; devices[i]; i++) {
+		wifi = (NMDeviceWifi *) devices[i];
+		g_object_ref (wifi);
+
+		if (   rescan_cutoff == 0
+		    || (rescan_cutoff > 0 && nm_device_wifi_get_last_scan (wifi) >= rescan_cutoff))
+			continue;
+
+		if (!scan_info) {
+			scan_info = g_new0 (ScanInfo, 1);
+			scan_info->out_indices = g_array_ref (out_indices);
+			scan_info->tmpl = tmpl;
+			scan_info->bssid_user = bssid_user;
+			scan_info->nmc = nmc;
+		}
+
+		nmc->should_wait++;
+		data = g_slice_new0 (WifiListData);
+		data->wifi = wifi;
+		data->scan_info = scan_info;
+		data->last_scan_id = g_signal_connect (wifi, "notify::" NM_DEVICE_WIFI_LAST_SCAN,
+		                                       G_CALLBACK (wifi_last_scan_updated), data);
+		data->scan_cancellable = g_cancellable_new ();
+		data->timeout_id = g_timeout_add_seconds (15, wifi_list_scan_timeout, data);
+		nm_device_wifi_request_scan_async (wifi, data->scan_cancellable, wifi_list_rescan_cb, data);
+	}
+
+	if (scan_info) {
+		scan_info->devices = g_steal_pointer (&devices);
 	} else {
+		/* Print results right away if no scan is pending */
 		for (i = 0; devices[i]; i++) {
-			NMDevice *dev = devices[i];
-
-			if (NM_IS_DEVICE_WIFI (dev)) {
-				wifi_list_aps (NM_DEVICE_WIFI (dev), nmc, out_indices, tmpl, bssid_user, rescan_cutoff);
-			}
+			wifi_print_aps (NM_DEVICE_WIFI (devices[i]),
+			                nmc, out_indices,
+			                tmpl, bssid_user);
+			g_object_unref (devices[i]);
 		}
 	}
 
diff --git a/clients/cli/utils.c b/clients/cli/utils.c
index e21c108d..feb67221 100644
--- a/clients/cli/utils.c
+++ b/clients/cli/utils.c
@@ -919,6 +919,8 @@ nmc_empty_output_fields (NmcOutputData *output_data)
 	/* Empty output_data array */
 	if (output_data->output_data->len > 0)
 		g_ptr_array_remove_range (output_data->output_data, 0, output_data->output_data->len);
+
+	g_ptr_array_unref (output_data->output_data);
 }
 
 /*****************************************************************************/