summary refs log tree commit diff
path: root/clients/cli/connections.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/cli/connections.c')
-rw-r--r--clients/cli/connections.c316
1 files changed, 123 insertions, 193 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c
index 0e4a95e6..44e34d56 100644
--- a/clients/cli/connections.c
+++ b/clients/cli/connections.c
@@ -490,9 +490,7 @@ _metagen_con_show_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
 	const char *s;
 	char *s_mut;
 
-	NMC_HANDLE_COLOR (  ac
-	                  ? nmc_active_connection_state_to_color (nm_active_connection_get_state (ac))
-	                  : NM_META_COLOR_CONNECTION_UNKNOWN);
+	NMC_HANDLE_COLOR (nmc_active_connection_state_to_color (ac));
 
 	if (c)
 		s_con = nm_connection_get_setting_connection (c);
@@ -541,6 +539,8 @@ _metagen_con_show_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
 			if (info->info_type == NMC_GENERIC_INFO_TYPE_CON_SHOW_TIMESTAMP)
 				return (*out_to_free = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp));
 			else {
+				struct tm localtime_result;
+
 				if (!timestamp) {
 					if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY)
 						return _("never");
@@ -548,7 +548,7 @@ _metagen_con_show_get_fcn (NMC_META_GENERIC_INFO_GET_FCN_ARGS)
 				}
 				timestamp_real = timestamp;
 				s_mut = g_malloc0 (128);
-				strftime (s_mut, 64, "%c", localtime (&timestamp_real));
+				strftime (s_mut, 127, "%c", localtime_r (&timestamp_real, &localtime_result));
 				return (*out_to_free = s_mut);
 			}
 		}
@@ -1425,8 +1425,18 @@ nmc_connection_profile_details (NMConnection *connection, NmCli *nmc)
 }
 
 NMMetaColor
-nmc_active_connection_state_to_color (NMActiveConnectionState state)
+nmc_active_connection_state_to_color (NMActiveConnection *ac)
 {
+	NMActiveConnectionState state;
+
+	if (!ac)
+		return NM_META_COLOR_CONNECTION_UNKNOWN;
+
+	if (NM_FLAGS_HAS (nm_active_connection_get_state_flags (ac), NM_ACTIVATION_STATE_FLAG_EXTERNAL))
+		return NM_META_COLOR_CONNECTION_EXTERNAL;
+
+	state = nm_active_connection_get_state (ac);
+
 	if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
 		return NM_META_COLOR_CONNECTION_ACTIVATING;
 	else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
@@ -1449,7 +1459,9 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc)
 	gboolean was_output = FALSE;
 
 	if (!nmc->required_fields || g_ascii_strcasecmp (nmc->required_fields, "common") == 0) {
+		/* pass */
 	} else if (!nmc->required_fields || g_ascii_strcasecmp (nmc->required_fields, "all") == 0) {
+		/* pass */
 	} else
 		fields_str = nmc->required_fields;
 
@@ -2074,6 +2086,7 @@ do_connections_show (const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
 		if (!nmc->required_fields || g_ascii_strcasecmp (nmc->required_fields, "common") == 0)
 			fields_str = NMC_FIELDS_CON_SHOW_COMMON;
 		else if (!nmc->required_fields || g_ascii_strcasecmp (nmc->required_fields, "all") == 0) {
+			/* pass */
 		} else
 			fields_str = nmc->required_fields;
 
@@ -2600,7 +2613,7 @@ progress_active_connection_cb (gpointer user_data)
 	}
 
 	str =   device
-	      ? gettext (nmc_device_state_to_string (nm_device_get_state (device)))
+	      ? gettext (nmc_device_state_to_string_with_external (device))
 	      : active_connection_state_to_string (ac_state);
 
 	nmc_terminal_show_progress (str);
@@ -2689,91 +2702,6 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat
 	}
 }
 
-/**
- * parse_passwords:
- * @passwd_file: file with passwords to parse
- * @error: location to store error, or %NULL
- *
- * Parse passwords given in @passwd_file and insert them into a hash table.
- * Example of @passwd_file contents:
- *   wifi.psk:tajne heslo
- *   802-1x.password:krakonos
- *   802-11-wireless-security:leap-password:my leap password
- *
- * Returns: hash table with parsed passwords, or %NULL on an error
- */
-static GHashTable *
-parse_passwords (const char *passwd_file, GError **error)
-{
-	gs_unref_hashtable GHashTable *pwds_hash = NULL;
-	gs_free char *contents = NULL;
-	gsize len = 0;
-	GError *local_err = NULL;
-	gs_free const char **strv = NULL;
-	const char *const*iter;
-	char *pwd_spec, *pwd, *prop;
-	const char *setting;
-
-	pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free);
-
-	if (!passwd_file)
-		return g_steal_pointer (&pwds_hash);
-
-	if (!g_file_get_contents (passwd_file, &contents, &len, &local_err)) {
-		g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-		             _("failed to read passwd-file '%s': %s"),
-		             passwd_file, local_err->message);
-		g_error_free (local_err);
-		return NULL;
-	}
-
-	strv = nm_utils_strsplit_set (contents, "\r\n");
-	for (iter = strv; strv && *iter; iter++) {
-		gs_free char *iter_s = g_strdup (*iter);
-
-		pwd = strchr (iter_s, ':');
-		if (!pwd) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("missing colon in 'password' entry '%s'"), *iter);
-			return NULL;
-		}
-		*(pwd++) = '\0';
-
-		prop = strchr (iter_s, '.');
-		if (!prop) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("missing dot in 'password' entry '%s'"), *iter);
-			return NULL;
-		}
-		*(prop++) = '\0';
-
-		setting = iter_s;
-		while (g_ascii_isspace (*setting))
-			setting++;
-		/* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */
-		if (!strcmp (setting, "wifi-sec") || !strcmp (setting, "wifi"))
-			setting = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
-		if (nm_setting_lookup_type (setting) == G_TYPE_INVALID) {
-			g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
-			             _("invalid setting name in 'password' entry '%s'"), setting);
-			return NULL;
-		}
-
-		if (   nm_streq (setting, "vpn")
-		    && g_str_has_prefix (prop, "secret.")) {
-			/* in 1.12.0, we wrongly required the VPN secrets to be named
-			 * "vpn.secret". It should be "vpn.secrets". Work around it
-			 * (rh#1628833). */
-			pwd_spec = g_strdup_printf ("vpn.secrets.%s", &prop[NM_STRLEN ("secret.")]);
-		} else
-			pwd_spec = g_strdup_printf ("%s.%s", setting, prop);
-
-		g_hash_table_insert (pwds_hash, pwd_spec, g_strdup (pwd));
-	}
-
-	return g_steal_pointer (&pwds_hash);
-}
-
 static gboolean
 nmc_activate_connection (NmCli *nmc,
                          NMConnection *connection,
@@ -2822,9 +2750,27 @@ nmc_activate_connection (NmCli *nmc,
 	}
 
 	/* Parse passwords given in passwords file */
-	pwds_hash = parse_passwords (pwds, error);
-	if (!pwds_hash)
-		return FALSE;
+	{
+		gs_free_error GError *local = NULL;
+		gssize error_line;
+
+		pwds_hash = nmc_utils_read_passwd_file (pwds, &error_line, &local);
+		if (!pwds_hash) {
+			if (error_line >= 0) {
+				g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+				             _("invalid passwd-file '%s' at line %zd: %s"),
+				             pwds,
+				             error_line,
+				             local->message);
+			} else {
+				g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT,
+				             _("invalid passwd-file '%s': %s"),
+				             pwds,
+				             local->message);
+			}
+			return FALSE;
+		}
+	}
 
 	if (nmc->pwds_hash)
 		g_hash_table_destroy (nmc->pwds_hash);
@@ -3506,10 +3452,10 @@ static const char *
 check_valid_name_toplevel (const char *val, const char **slave_type, GError **error)
 {
 	gs_unref_ptrarray GPtrArray *tmp_arr = NULL;
+	const NMMetaSettingInfoEditor *setting_info;
+	gs_free_error GError *tmp_err = NULL;
 	const char *str;
-	GError *tmp_err = NULL;
 	int i;
-	const NMMetaSettingInfoEditor *setting_info;
 
 	NM_SET_OUT (slave_type, NULL);
 
@@ -3530,14 +3476,13 @@ check_valid_name_toplevel (const char *val, const char **slave_type, GError **er
 	str = nmc_string_is_valid (val, (const char **) tmp_arr->pdata, &tmp_err);
 	if (!str) {
 		if (tmp_err->code == 1)
-			g_propagate_error (error, tmp_err);
+			g_propagate_error (error, g_steal_pointer (&tmp_err));
 		else {
 			/* We want to handle aliases, so construct own error message */
-			char *err_str = get_valid_options_string_toplevel ();
+			gs_free char *err_str = NULL;
 
+			err_str = get_valid_options_string_toplevel ();
 			g_set_error (error, 1, 0, _("'%s' not among [%s]"), val, err_str);
-			g_free (err_str);
-			g_clear_error (&tmp_err);
 		}
 		return NULL;
 	}
@@ -3731,15 +3676,12 @@ is_setting_valid (NMConnection *connection, const NMMetaSettingValidPartItem *co
 static char *
 is_property_valid (NMSetting *setting, const char *property, GError **error)
 {
-	char **valid_props = NULL;
+	gs_strfreev char **valid_props = NULL;
 	const char *prop_name;
-	char *ret;
 
 	valid_props = nmc_setting_get_valid_properties (setting);
 	prop_name = nmc_string_is_valid (property, (const char **) valid_props, error);
-	ret = g_strdup (prop_name);
-	g_strfreev (valid_props);
-	return ret;
+	return g_strdup (prop_name);
 }
 
 static char *
@@ -6034,19 +5976,23 @@ extract_setting_and_property (const char *prompt, const char *line,
 }
 
 static void
-get_setting_and_property (const char *prompt, const char *line,
-                          NMSetting **setting_out, char**property_out)
+get_setting_and_property (const char *prompt,
+                          const char *line,
+                          NMSetting **setting_out,
+                          char **property_out)
 {
 	const NMMetaSettingValidPartItem *const*valid_settings_main;
 	const NMMetaSettingValidPartItem *const*valid_settings_slave;
-	const char *setting_name;
-	NMSetting *setting = NULL;
-	char *property = NULL;
-	char *sett = NULL, *prop = NULL;
+	gs_unref_object NMSetting *setting = NULL;
+	gs_free char *property = NULL;
 	NMSettingConnection *s_con;
+	gs_free char *sett = NULL;
+	gs_free char *prop = NULL;
 	const char *s_type = NULL;
+	const char *setting_name;
 
 	extract_setting_and_property (prompt, line, &sett, &prop);
+
 	if (sett) {
 		/* Is this too much (and useless?) effort for an unlikely case? */
 		s_con = nm_connection_get_setting_connection (nmc_tab_completion.connection);
@@ -6056,23 +6002,22 @@ get_setting_and_property (const char *prompt, const char *line,
 		valid_settings_main = get_valid_settings_array (nmc_tab_completion.con_type);
 		valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type (s_type, NULL);
 
-		setting_name = check_valid_name (sett, valid_settings_main,
-		                                 valid_settings_slave,  NULL);
+		setting_name = check_valid_name (sett,
+		                                 valid_settings_main,
+		                                 valid_settings_slave,
+		                                 NULL);
 		setting = nm_meta_setting_info_editor_new_setting (nm_meta_setting_info_editor_find_by_name (setting_name, FALSE),
 		                                                   NM_META_ACCESSOR_SETTING_INIT_TYPE_DEFAULT);
 	} else
-		setting = nmc_tab_completion.setting ? g_object_ref (nmc_tab_completion.setting) : NULL;
+		setting = nm_g_object_ref (nmc_tab_completion.setting);
 
 	if (setting && prop)
 		property = is_property_valid (setting, prop, NULL);
 	else
 		property = g_strdup (nmc_tab_completion.property);
 
-	*setting_out = setting;
-	*property_out = property;
-
-	g_free (sett);
-	g_free (prop);
+	*setting_out = g_steal_pointer (&setting);
+	*property_out = g_steal_pointer (&property);
 }
 
 static gboolean
@@ -6082,7 +6027,7 @@ _get_and_check_property (const char *prompt,
                          const char **array_multi,
                          gboolean *multi)
 {
-	char *prop;
+	gs_free char *prop = NULL;
 	gboolean found = FALSE;
 
 	extract_setting_and_property (prompt, line, NULL, &prop);
@@ -6091,7 +6036,6 @@ _get_and_check_property (const char *prompt,
 			found = !!nmc_string_is_valid (prop, array, NULL);
 		if (array_multi && multi)
 			*multi = !!nmc_string_is_valid (prop, array_multi, NULL);
-		g_free (prop);
 	}
 	return found;
 }
@@ -6169,33 +6113,26 @@ should_complete_property_values (const char *prompt, const char *line, gboolean
 static gboolean
 _setting_property_is_boolean (NMSetting *setting, const char *property_name)
 {
-	GParamSpec *pspec;
+	const GParamSpec *pspec;
 
-	g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
-	g_return_val_if_fail (property_name, FALSE);
+	nm_assert (NM_IS_SETTING (setting));
+	nm_assert (property_name);
 
 	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name);
-	if (pspec && pspec->value_type == G_TYPE_BOOLEAN)
-		return TRUE;
-	return FALSE;
+	return    pspec
+	       && pspec->value_type == G_TYPE_BOOLEAN;
 }
 
 static gboolean
 should_complete_boolean (const char *prompt, const char *line)
 {
-	NMSetting *setting;
-	char *property;
-	gboolean is_boolean = FALSE;
+	gs_unref_object NMSetting *setting = NULL;
+	gs_free char *property = NULL;
 
 	get_setting_and_property (prompt, line, &setting, &property);
-	if (setting && property)
-		is_boolean = _setting_property_is_boolean (setting, property);
-
-	if (setting)
-		g_object_unref (setting);
-	g_free (property);
-
-	return is_boolean;
+	return    setting
+	       && property
+	       && _setting_property_is_boolean (setting, property);
 }
 
 static char *
@@ -6222,11 +6159,11 @@ extern int rl_complete_with_tilde_expansion;
 static char **
 nmcli_editor_tab_completion (const char *text, int start, int end)
 {
-	char **match_array = NULL;
-	const char *line = rl_line_buffer;
 	rl_compentry_func_t *generator_func = NULL;
-	char *prompt_tmp;
-	char *word = NULL;
+	const char *line = rl_line_buffer;
+	gs_free char *prompt_tmp = NULL;
+	gs_free char *word = NULL;
+	char **match_array = NULL;
 	size_t n1;
 	int num;
 
@@ -6280,7 +6217,7 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
 							rl_completion_append_character = '.';
 						} else
 							generator_func = gen_property_names;
-					} else if (num >= 3) {
+					} else {
 						if (num == 3 && should_complete_files (NULL, line))
 							rl_attempted_completion_over = 0;
 						else if (should_complete_vpn_uuids (NULL, line)) {
@@ -6350,8 +6287,6 @@ nmcli_editor_tab_completion (const char *text, int start, int end)
 	if (generator_func)
 		match_array = rl_completion_matches (text, generator_func);
 
-	g_free (prompt_tmp);
-	g_free (word);
 	return match_array;
 }
 
@@ -6391,49 +6326,44 @@ load_history_cmds (const char *uuid)
 static void
 save_history_cmds (const char *uuid)
 {
-	HIST_ENTRY **hist = NULL;
-	GKeyFile *kf;
-	char *filename;
-	size_t i;
-	char *key;
-	char *data;
-	gsize len = 0;
-	GError *err = NULL;
+	gs_unref_keyfile GKeyFile *kf = NULL;
+	gs_free_error GError *error = NULL;
+	gs_free char *filename = NULL;
+	gs_free char *data = NULL;
+	HIST_ENTRY **hist;
+	gsize len;
+	gsize i;
 
 	hist = history_list ();
-	if (hist) {
-		filename = g_build_filename (g_get_home_dir (), NMCLI_EDITOR_HISTORY, NULL);
-		kf = g_key_file_new ();
-		if (!g_key_file_load_from_file (kf, filename, G_KEY_FILE_KEEP_COMMENTS, &err)) {
-			if (   !g_error_matches (err, G_FILE_ERROR, G_FILE_ERROR_NOENT)
-			    && !g_error_matches (err, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
-				g_print ("Warning: %s parse error: %s\n", filename, err->message);
-				g_key_file_free (kf);
-				g_free (filename);
-				g_clear_error (&err);
-				return;
-			}
-			g_clear_error (&err);
-		}
+	if (!hist)
+		return;
 
-		/* Remove previous history group and save new history entries */
-		g_key_file_remove_group (kf, uuid, NULL);
-		for (i = 0; hist[i]; i++)
-		{
-			key = g_strdup_printf ("%zd", i);
-			g_key_file_set_string (kf, uuid, key, hist[i]->line);
-			g_free (key);
-		}
+	filename = g_build_filename (g_get_home_dir (), NMCLI_EDITOR_HISTORY, NULL);
+
+	kf = g_key_file_new ();
 
-		/* Write history to file */
-		data = g_key_file_to_data (kf, &len, NULL);
-		if (data) {
-			g_file_set_contents (filename, data, len, NULL);
-			g_free (data);
+	if (!g_key_file_load_from_file (kf, filename, G_KEY_FILE_KEEP_COMMENTS, &error)) {
+		if (   !g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)
+		    && !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
+			g_print ("Warning: %s parse error: %s\n", filename, error->message);
+			return;
 		}
-		g_key_file_free (kf);
-		g_free (filename);
+		g_clear_error (&error);
+	}
+
+	/* Remove previous history group and save new history entries */
+	g_key_file_remove_group (kf, uuid, NULL);
+	for (i = 0; hist[i]; i++) {
+		char key[100];
+
+		nm_sprintf_buf (key, "%zd", i);
+		g_key_file_set_string (kf, uuid, key, hist[i]->line);
 	}
+
+	/* Write history to file */
+	data = g_key_file_to_data (kf, &len, NULL);
+	if (data)
+		g_file_set_contents (filename, data, len, NULL);
 }
 
 /*****************************************************************************/
@@ -6890,7 +6820,7 @@ progress_activation_editor_cb (gpointer user_data)
 	ac_state = nm_active_connection_get_state (ac);
 	dev_state = nm_device_get_state (device);
 
-	nmc_terminal_show_progress (gettext (nmc_device_state_to_string (dev_state)));
+	nmc_terminal_show_progress (gettext (nmc_device_state_to_string_with_external (device)));
 
 	if (   ac_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
 	    || dev_state == NM_DEVICE_STATE_ACTIVATED) {
@@ -7181,9 +7111,10 @@ property_edit_submenu (NmCli *nmc,
 				else
 					g_print (_("Unknown command argument: '%s'\n"), cmd_property_arg);
 			} else {
-				char *prop_val =  nmc_setting_get_property (curr_setting, prop_name, NULL);
+				gs_free char *prop_val = NULL;
+
+				prop_val = nmc_setting_get_property (curr_setting, prop_name, NULL);
 				g_print ("%s: %s\n", prop_name, prop_val);
-				g_free (prop_val);
 			}
 			break;
 
@@ -7265,7 +7196,7 @@ ask_check_setting (const NmcConfig *nmc_config,
                    const NMMetaSettingValidPartItem *const*valid_settings_slave,
                    const char *valid_settings_str)
 {
-	char *setting_name_user;
+	gs_free char *setting_name_user = NULL;
 	const char *setting_name;
 	GError *err = NULL;
 
@@ -7285,7 +7216,6 @@ ask_check_setting (const NmcConfig *nmc_config,
 		g_print (_("Error: invalid setting name; %s\n"), err->message);
 		g_clear_error (&err);
 	}
-	g_free (setting_name_user);
 	return setting_name;
 }
 
@@ -7295,9 +7225,9 @@ ask_check_property (const NmcConfig *nmc_config,
                     const char **valid_props,
                     const char *valid_props_str)
 {
-	char *prop_name_user;
+	gs_free_error GError *tmp_err = NULL;
+	gs_free char *prop_name_user = NULL;
 	const char *prop_name;
-	GError *tmp_err = NULL;
 
 	if (!arg) {
 		g_print (_("Available properties: %s\n"), valid_props_str);
@@ -7307,11 +7237,10 @@ ask_check_property (const NmcConfig *nmc_config,
 	} else
 		prop_name_user = g_strdup (arg);
 
-	if (!(prop_name = nmc_string_is_valid (prop_name_user, valid_props, &tmp_err))) {
+	prop_name = nmc_string_is_valid (prop_name_user, valid_props, &tmp_err);
+	if (!prop_name)
 		g_print (_("Error: property %s\n"), tmp_err->message);
-		g_clear_error (&tmp_err);
-	}
-	g_free (prop_name_user);
+
 	return prop_name;
 }
 
@@ -7325,6 +7254,7 @@ update_connection_timestamp (NMConnection *src, NMConnection *dst)
 	s_con_dst = nm_connection_get_setting_connection (dst);
 	if (s_con_src && s_con_dst) {
 		guint64 timestamp = nm_setting_connection_get_timestamp (s_con_src);
+
 		g_object_set (s_con_dst, NM_SETTING_CONNECTION_TIMESTAMP, timestamp, NULL);
 	}
 }