about summary refs log tree commit diff
path: root/clients/cli/nmcli.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/cli/nmcli.c')
-rw-r--r--clients/cli/nmcli.c341
1 files changed, 215 insertions, 126 deletions
diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c
index 6407f50b..bbfc310d 100644
--- a/clients/cli/nmcli.c
+++ b/clients/cli/nmcli.c
@@ -51,6 +51,42 @@
 # define NMCLI_VERSION VERSION
 #endif
 
+#define DEFAULT_PALETTE_INIT \
+	[NM_META_COLOR_CONNECTION_ACTIVATED]     = "32", \
+	[NM_META_COLOR_CONNECTION_ACTIVATING]    = "33", \
+	[NM_META_COLOR_CONNECTION_DISCONNECTING] = "31", \
+	[NM_META_COLOR_CONNECTION_INVISIBLE]     =  "2", \
+	[NM_META_COLOR_CONNECTIVITY_FULL]        = "32", \
+	[NM_META_COLOR_CONNECTIVITY_LIMITED]     = "33", \
+	[NM_META_COLOR_CONNECTIVITY_NONE]        = "31", \
+	[NM_META_COLOR_CONNECTIVITY_PORTAL]      = "33", \
+	[NM_META_COLOR_DEVICE_ACTIVATED]         = "32", \
+	[NM_META_COLOR_DEVICE_ACTIVATING]        = "33", \
+	[NM_META_COLOR_DEVICE_DISCONNECTED]      = "31", \
+	[NM_META_COLOR_DEVICE_FIRMWARE_MISSING]  = "31", \
+	[NM_META_COLOR_DEVICE_PLUGIN_MISSING]    = "31", \
+	[NM_META_COLOR_DEVICE_UNAVAILABLE]       =  "2", \
+	[NM_META_COLOR_MANAGER_RUNNING]          = "32", \
+	[NM_META_COLOR_MANAGER_STARTING]         = "33", \
+	[NM_META_COLOR_MANAGER_STOPPED]          = "31", \
+	[NM_META_COLOR_PERMISSION_AUTH]          = "33", \
+	[NM_META_COLOR_PERMISSION_NO]            = "31", \
+	[NM_META_COLOR_PERMISSION_YES]           = "32", \
+	[NM_META_COLOR_STATE_ASLEEP]             = "31", \
+	[NM_META_COLOR_STATE_CONNECTED_GLOBAL]   = "32", \
+	[NM_META_COLOR_STATE_CONNECTED_LOCAL]    = "32", \
+	[NM_META_COLOR_STATE_CONNECTED_SITE]     = "32", \
+	[NM_META_COLOR_STATE_CONNECTING]         = "33", \
+	[NM_META_COLOR_STATE_DISCONNECTED]       = "31", \
+	[NM_META_COLOR_STATE_DISCONNECTING]      = "33", \
+	[NM_META_COLOR_WIFI_SIGNAL_EXCELLENT]    = "32", \
+	[NM_META_COLOR_WIFI_SIGNAL_FAIR]         = "35", \
+	[NM_META_COLOR_WIFI_SIGNAL_GOOD]         = "33", \
+	[NM_META_COLOR_WIFI_SIGNAL_POOR]         = "36", \
+	[NM_META_COLOR_WIFI_SIGNAL_UNKNOWN]      =  "2", \
+	[NM_META_COLOR_ENABLED]                  = "32", \
+	[NM_META_COLOR_DISABLED]                 = "31", \
+
 NmCli nm_cli = {
 	.client = NULL,
 
@@ -74,40 +110,7 @@ NmCli nm_cli = {
 	.nmc_config.show_secrets = FALSE,
 	.nmc_config.in_editor = FALSE,
 	.nmc_config.palette = {
-		[NM_META_COLOR_CONNECTION_ACTIVATED]	 = "32",
-		[NM_META_COLOR_CONNECTION_ACTIVATING]	 = "33",
-		[NM_META_COLOR_CONNECTION_DISCONNECTING] = "31",
-		[NM_META_COLOR_CONNECTION_INVISIBLE]	 = "2",
-		[NM_META_COLOR_CONNECTIVITY_FULL]	 = "32",
-		[NM_META_COLOR_CONNECTIVITY_LIMITED]	 = "33",
-		[NM_META_COLOR_CONNECTIVITY_NONE]	 = "31",
-		[NM_META_COLOR_CONNECTIVITY_PORTAL]	 = "33",
-		[NM_META_COLOR_DEVICE_ACTIVATED]	 = "32",
-		[NM_META_COLOR_DEVICE_ACTIVATING]	 = "33",
-		[NM_META_COLOR_DEVICE_DISCONNECTED]	 = "31",
-		[NM_META_COLOR_DEVICE_FIRMWARE_MISSING]	 = "31",
-		[NM_META_COLOR_DEVICE_PLUGIN_MISSING]	 = "31",
-		[NM_META_COLOR_DEVICE_UNAVAILABLE]	 = "2",
-		[NM_META_COLOR_MANAGER_RUNNING]		 = "32",
-		[NM_META_COLOR_MANAGER_STARTING]	 = "33",
-		[NM_META_COLOR_MANAGER_STOPPED]		 = "31",
-		[NM_META_COLOR_PERMISSION_AUTH]		 = "33",
-		[NM_META_COLOR_PERMISSION_NO]		 = "31",
-		[NM_META_COLOR_PERMISSION_YES]		 = "32",
-		[NM_META_COLOR_STATE_ASLEEP]		 = "31",
-		[NM_META_COLOR_STATE_CONNECTED_GLOBAL]	 = "32",
-		[NM_META_COLOR_STATE_CONNECTED_LOCAL]	 = "32",
-		[NM_META_COLOR_STATE_CONNECTED_SITE]	 = "32",
-		[NM_META_COLOR_STATE_CONNECTING]	 = "33",
-		[NM_META_COLOR_STATE_DISCONNECTED]	 = "31",
-		[NM_META_COLOR_STATE_DISCONNECTING]	 = "33",
-		[NM_META_COLOR_WIFI_SIGNAL_EXCELLENT]	 = "32",
-		[NM_META_COLOR_WIFI_SIGNAL_FAIR]	 = "35",
-		[NM_META_COLOR_WIFI_SIGNAL_GOOD]	 = "33",
-		[NM_META_COLOR_WIFI_SIGNAL_POOR]	 = "36",
-		[NM_META_COLOR_WIFI_SIGNAL_UNKNOWN]	 = "2",
-		[NM_META_COLOR_ENABLED]			 = "32",
-		[NM_META_COLOR_DISABLED]		 = "31",
+		DEFAULT_PALETTE_INIT
 	},
 	.editor_status_line = FALSE,
 	.editor_save_confirmation = TRUE,
@@ -186,19 +189,19 @@ complete_fields (const char *option, const char *prefix)
 	h = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
 
 	complete_field (h, metagen_ip4_config);
-	complete_field (h, nmc_fields_dhcp_config);
-	complete_field (h, nmc_fields_ip6_config);
+	complete_field (h, metagen_dhcp_config);
+	complete_field (h, metagen_ip6_config);
 	complete_field (h, metagen_con_show);
 	complete_field (h, metagen_con_active_general);
-	complete_field (h, nmc_fields_con_active_details_vpn);
+	complete_field (h, metagen_con_active_vpn);
 	complete_field (h, nmc_fields_con_active_details_groups);
-	complete_field (h, nmc_fields_dev_status);
-	complete_field (h, nmc_fields_dev_show_general);
-	complete_field (h, nmc_fields_dev_show_connections);
-	complete_field (h, nmc_fields_dev_show_cap);
-	complete_field (h, nmc_fields_dev_show_wired_prop);
-	complete_field (h, nmc_fields_dev_show_wifi_prop);
-	complete_field (h, nmc_fields_dev_show_wimax_prop);
+	complete_field (h, metagen_device_status);
+	complete_field (h, metagen_device_detail_general);
+	complete_field (h, metagen_device_detail_connections);
+	complete_field (h, metagen_device_detail_capabilities);
+	complete_field (h, metagen_device_detail_wired_properties);
+	complete_field (h, metagen_device_detail_wifi_properties);
+	complete_field (h, metagen_device_detail_wimax_properties);
 	complete_field (h, nmc_fields_dev_wifi_list);
 	complete_field (h, nmc_fields_dev_wimax_list);
 	complete_field (h, nmc_fields_dev_show_master_prop);
@@ -337,76 +340,162 @@ typedef enum {
         NMC_USE_COLOR_NO,
 } NmcColorOption;
 
-/* Checks whether a particular terminal-colors.d(5) file (.enabled, .disabled or .schem)
- * exists. If contents is non-NULL, it returns the content. */
-static gboolean
-check_colors_file (NmCli *nmc, NmcColorOption *color_option,
-                   const char *base_dir, const char *name, const char *term, const char *type,
-                   char **contents)
+static char *
+check_colors_construct_filename (const char *base_dir,
+                                 const char *name,
+                                 const char *term,
+                                 const char *type)
 {
-	char *filename;
-	gboolean exists;
-
-	filename = g_strdup_printf ("%s/terminal-colors.d/%s%s%s%s%s",
-	                            base_dir,
-	                            name ? name : "",
-	                            term ? "@" : "", term ? term : "",
-	                            (name || term) ? "." : "",
-	                            type);
-	if (contents)
-		exists = g_file_get_contents (filename, contents, NULL, NULL);
-	else
-		exists = g_file_test (filename, G_FILE_TEST_EXISTS);
-	g_free (filename);
+	return g_strdup_printf ("%s/terminal-colors.d/%s%s%s%s%s",
+	                        base_dir,
+	                        name ? name : "",
+	                        term ? "@" : "", term ? term : "",
+	                        (name || term) ? "." : "",
+	                        type);
+}
+
+static NmcColorOption
+check_colors_check_enabled_one_file (const char *base_dir,
+                                     const char *name,
+                                     const char *term)
+{
+	gs_free char *filename_e = NULL;
+	gs_free char *filename_d = NULL;
+
+	filename_e = check_colors_construct_filename (base_dir, name, term, "enable");
+	if (g_file_test (filename_e, G_FILE_TEST_EXISTS))
+		return NMC_USE_COLOR_YES;
+
+	filename_d = check_colors_construct_filename (base_dir, name, term, "disable");
+	if (g_file_test (filename_d, G_FILE_TEST_EXISTS))
+		return NMC_USE_COLOR_NO;
 
-	return exists;
+	return NMC_USE_COLOR_AUTO;
 }
 
-static void
-check_colors_files_for_term (NmCli *nmc, NmcColorOption *color_option,
-                             const char *base_dir, const char *name, const char *term)
+static char *
+check_colors_check_palette_one_file (const char *base_dir,
+                                     const char *name,
+                                     const char *term)
 {
-	if (   *color_option == NMC_USE_COLOR_AUTO
-	    && check_colors_file (nmc, color_option, base_dir, name, term, "enable", NULL)) {
-		*color_option = NMC_USE_COLOR_YES;
-	}
+	gs_free char *filename = check_colors_construct_filename (base_dir, name, term, "schem");
+	char *contents;
 
-	if (   *color_option == NMC_USE_COLOR_AUTO
-	    && check_colors_file (nmc, color_option, base_dir, name, term, "disable", NULL)) {
-		*color_option = NMC_USE_COLOR_NO;
-	}
+	if (g_file_get_contents (filename, &contents, NULL, NULL))
+		return contents;
+	return NULL;
+}
 
-	if (*color_option == NMC_USE_COLOR_NO) {
-		/* No need to bother any further. */
-		return;
-	}
+static gboolean
+check_colors_check_enabled (const char *base_dir_1, const char *base_dir_2, const char *name, const char *term)
+{
+	int i;
+
+	if (term && strchr (term, '/'))
+		term = NULL;
+
+#define CHECK_AND_RETURN(cmd) \
+	G_STMT_START { \
+		NmcColorOption _color_option; \
+		\
+		_color_option = (cmd); \
+		if (_color_option != NMC_USE_COLOR_AUTO) \
+			return _color_option == NMC_USE_COLOR_YES; \
+	} G_STMT_END
+
+	for (i = 0; i < 2; i++) {
+		const char *base_dir = (i == 0 ? base_dir_1 : base_dir_2);
 
-	if (nmc->palette_buffer == NULL)
-		check_colors_file (nmc, color_option, base_dir, name, term, "schem", &nmc->palette_buffer);
+		if (!base_dir)
+			continue;
+		if (name && term)
+			CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, name, term));
+		if (name)
+			CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, name, NULL));
+		if (term)
+			CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, NULL, term));
+		if (TRUE)
+			CHECK_AND_RETURN (check_colors_check_enabled_one_file (base_dir, NULL, NULL));
+	}
+#undef CHECK_AND_RETURN
+	return TRUE;
 }
 
-static void
-check_colors_files_for_name (NmCli *nmc, NmcColorOption *color_option,
-                             const char *base_dir, const char *name)
+static char *
+check_colors_check_palette (const char *base_dir_1, const char *base_dir_2, const char *name, const char *term)
 {
-	const gchar *term;
+	int i;
 
-	/* Take a shortcut if the directory is not there. */
-	if (!g_file_test (base_dir, G_FILE_TEST_EXISTS))
-		return;
+	if (term && strchr (term, '/'))
+		term = NULL;
 
-	term = g_getenv ("TERM");
-	if (term)
-		check_colors_files_for_term (nmc, color_option, base_dir, name, term);
-	check_colors_files_for_term (nmc, color_option, base_dir, name, NULL);
+#define CHECK_AND_RETURN(cmd) \
+	G_STMT_START { \
+		char *_palette; \
+		\
+		_palette = (cmd); \
+		if (_palette) \
+			return _palette; \
+	} G_STMT_END
+
+	for (i = 0; i < 2; i++) {
+		const char *base_dir = (i == 0 ? base_dir_1 : base_dir_2);
+
+		if (!base_dir)
+			continue;
+		if (name && term)
+			CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, name, term));
+		if (name)
+			CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, name, NULL));
+		if (term)
+			CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, NULL, term));
+		if (TRUE)
+			CHECK_AND_RETURN (check_colors_check_palette_one_file (base_dir, NULL, NULL));
+	}
+#undef CHECK_AND_RETURN
+	return NULL;
 }
 
-static void
-check_colors_files_for_base_dir (NmCli *nmc, NmcColorOption *color_option,
-                                 const char *base_dir)
+static gboolean
+check_colors (NmcColorOption color_option,
+              char **out_palette_str)
 {
-	check_colors_files_for_name (nmc, color_option, base_dir, "nmcli");
-	check_colors_files_for_name (nmc, color_option, base_dir, NULL);
+	const char *base_dir_1, *base_dir_2;
+	const char *const NAME = "nmcli";
+	const char *term;
+
+	*out_palette_str = NULL;
+
+	if (!NM_IN_SET (color_option, NMC_USE_COLOR_AUTO, NMC_USE_COLOR_YES)) {
+		/* nothing to do. Colors are disabled. */
+		return FALSE;
+	}
+
+	term = g_getenv ("TERM");
+
+	if (color_option == NMC_USE_COLOR_AUTO) {
+		if (   nm_streq0 (term, "dumb")
+		    || !isatty (STDOUT_FILENO))
+			return FALSE;
+	}
+
+	base_dir_1 = g_get_user_config_dir ();
+	base_dir_2 = ""SYSCONFDIR;
+
+	if (base_dir_1) {
+		if (   nm_streq (base_dir_1, base_dir_2)
+		    || !g_file_test (base_dir_1, G_FILE_TEST_EXISTS))
+			base_dir_1 = NULL;
+	}
+	if (!g_file_test (base_dir_2, G_FILE_TEST_EXISTS))
+		base_dir_2 = NULL;
+
+	if (   color_option == NMC_USE_COLOR_AUTO
+	    && !check_colors_check_enabled (base_dir_1, base_dir_2, NAME, term))
+		return FALSE;
+
+	*out_palette_str = check_colors_check_palette (base_dir_1, base_dir_2, NAME, term);
+	return TRUE;
 }
 
 static const char *
@@ -415,7 +504,7 @@ resolve_color_alias (const char *color)
 	static const struct {
 		const char *name;
 		const char *alias;
-	} aliases[] = {
+	} const aliases[] = {
 		{ "reset",        "0" },
 		{ "bold",         "1" },
 		{ "white",        "1;37" },
@@ -455,12 +544,17 @@ resolve_color_alias (const char *color)
 }
 
 static gboolean
-parse_color_scheme (NmCli *nmc, GError **error)
+parse_color_scheme (char *palette_buffer,
+                    const char **palette /* _NM_META_COLOR_NUM elements */,
+                    GError **error)
 {
-	char *p = nmc->palette_buffer;
+	char *p = palette_buffer;
 	const char *name;
 	const char *color;
-	const char *map[_NM_META_COLOR_NUM] = {
+	const char *tmp_palette[_NM_META_COLOR_NUM] = {
+		DEFAULT_PALETTE_INIT
+	};
+	static const char *const map[_NM_META_COLOR_NUM] = {
 		[NM_META_COLOR_NONE]                     = NULL,
 		[NM_META_COLOR_CONNECTION_ACTIVATED]     = "connection-activated",
 		[NM_META_COLOR_CONNECTION_ACTIVATING]    = "connection-activating",
@@ -573,7 +667,7 @@ parse_color_scheme (NmCli *nmc, GError **error)
 		/* All good, set the palette entry. */
 		for (i = NM_META_COLOR_NONE + 1; i < _NM_META_COLOR_NUM; i++) {
 			if (strcmp (map[i], name) == 0) {
-				nmc->nmc_config_mutable.palette[i] = resolve_color_alias (color);
+				tmp_palette[i] = resolve_color_alias (color);
 				break;
 			}
 		}
@@ -581,38 +675,30 @@ parse_color_scheme (NmCli *nmc, GError **error)
 			g_debug ("Ignoring an unrecognized color: '%s'\n", name);
 	}
 
+	memcpy (palette, tmp_palette, sizeof (tmp_palette));
 	return TRUE;
 }
 
 static void
-set_colors (NmCli *nmc, NmcColorOption color_option)
+set_colors (NmcColorOption color_option,
+            bool *out_use_colors,
+            char **out_palette_buffer,
+            const char **palette /* _NM_META_COLOR_NUM elements */)
 {
-	GError *error = NULL;
-
-	if (color_option == NMC_USE_COLOR_AUTO) {
-		if (   g_strcmp0 (g_getenv ("TERM"), "dumb") == 0
-		    || !isatty (STDOUT_FILENO))
-			color_option = NMC_USE_COLOR_NO;
-	}
+	gs_free char *palette_str = NULL;
+	gboolean use_colors;
 
-	check_colors_files_for_base_dir (nmc, &color_option, g_get_user_config_dir ());
-	check_colors_files_for_base_dir (nmc, &color_option, SYSCONFDIR);
+	use_colors = check_colors (color_option, &palette_str);
 
-	switch (color_option) {
-	case NMC_USE_COLOR_YES:
-	case NMC_USE_COLOR_AUTO:
-		nmc->nmc_config_mutable.use_colors = TRUE;
-		break;
-	case NMC_USE_COLOR_NO:
-		nmc->nmc_config_mutable.use_colors = FALSE;
-		break;
-	}
+	*out_use_colors = use_colors;
+	if (use_colors && palette_str) {
+		GError *error = NULL;
 
-	if (nmc->nmc_config_mutable.use_colors && nmc->palette_buffer) {
-		if (!parse_color_scheme (nmc, &error)) {
+		if (!parse_color_scheme (palette_str, palette, &error)) {
 			g_debug ("Error parsing color scheme: %s", error->message);
 			g_error_free (error);
-		}
+		} else
+			*out_palette_buffer = g_steal_pointer (&palette_str);
 	}
 }
 
@@ -771,7 +857,10 @@ process_command_line (NmCli *nmc, int argc, char **argv)
 	if (nmc->required_fields)
 		nmc->nmc_config_mutable.overview = FALSE;
 
-	set_colors (nmc, colors);
+	set_colors (colors,
+	            &nmc->nmc_config_mutable.use_colors,
+	            &nmc->palette_buffer,
+	            nmc->nmc_config_mutable.palette);
 
 	/* Now run the requested command */
 	nmc_do_cmd (nmc, nmcli_cmds, *argv, argc, argv);