From 41d52e582bb90710d2c02fc649505421df9e262c Mon Sep 17 00:00:00 2001
From: Tambet Ingo <tambet@gmail.com>
Date: Wed, 3 Dec 2008 12:19:43 +0200
Subject: [PATCH] nm-fix-hosts-updating


diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c
index a97103c..a31baca 100644
--- a/src/NetworkManagerPolicy.c
+++ b/src/NetworkManagerPolicy.c
@@ -250,84 +250,54 @@ get_best_device (NMManager *manager, NMActRequest **out_req)
 #define FALLBACK_HOSTNAME "localhost.localdomain"
 
 static gboolean
-update_etc_hosts (const char *hostname)
+update_etc_hosts (const char *hostname, const char *domain)
 {
+	char *new_contents;
 	char *contents = NULL;
-	char **lines = NULL, **line;
 	GError *error = NULL;
-	gboolean initial_comments = TRUE;
-	gboolean added = FALSE;
-	gsize contents_len = 0;
-	GString *new_contents;
+	const char *hosts = SYSCONFDIR "/hosts";
+	gsize contents_len;
 	gboolean success = FALSE;
 
-	g_return_val_if_fail (hostname != NULL, FALSE);
-
-	if (!g_file_get_contents (SYSCONFDIR "/hosts", &contents, &contents_len, &error)) {
-		nm_warning ("%s: couldn't read " SYSCONFDIR "/hosts: (%d) %s",
-		            __func__, error ? error->code : 0,
-		            (error && error->message) ? error->message : "(unknown)");
+	if (!g_file_get_contents (hosts, &contents, &contents_len, &error)) {
+		g_warning ("%s: couldn't read %s: (%d) %s",
+				   __func__, hosts, error ? error->code : 0,
+				   (error && error->message) ? error->message : "(unknown)");
 		if (error)
 			g_error_free (error);
 	} else {
-		lines = g_strsplit_set (contents, "\n\r", 0);
-		g_free (contents);
-	}
-
-	new_contents = g_string_sized_new (contents_len ? contents_len + 100 : 200);
-	if (!new_contents) {
-		nm_warning ("%s: not enough memory to update " SYSCONFDIR "/hosts", __func__);
-		return FALSE;
-	}
-
-	/* Replace any 127.0.0.1 entry that is at the beginning of the file or right
-	 * after initial comments.  If there is no 127.0.0.1 entry at the beginning
-	 * or after initial comments, add one there and ignore any other 127.0.0.1
-	 * entries.
-	 */
-	for (line = lines; lines && *line; line++) {
-		gboolean add_line = TRUE;
-
-		/* This is the first line after the initial comments */
-		if (initial_comments && (*line[0] != '#')) {
-			initial_comments = FALSE;
-			g_string_append_printf (new_contents, "127.0.0.1\t%s", hostname);
-			if (strcmp (hostname, FALLBACK_HOSTNAME))
-				g_string_append_printf (new_contents, "\t" FALLBACK_HOSTNAME);
-			g_string_append (new_contents, "\tlocalhost\n");
-			added = TRUE;
-
-			/* Don't add the entry if it's supposed to be the actual localhost reverse mapping */
-			if (!strncmp (*line, "127.0.0.1", strlen ("127.0.0.1")) && strstr (*line, "localhost"))
-				add_line = FALSE;
+		GRegex *regex;
+		GString *replacement;
+
+		replacement = g_string_new ("127.0.0.2\t");
+		g_string_append (replacement, hostname);
+		if (domain) {
+			g_string_append_c (replacement, '.');
+			g_string_append (replacement, domain);
+			g_string_append_c (replacement, ' ');
+			g_string_append (replacement, hostname);
 		}
 
-		if (add_line) {
-			g_string_append (new_contents, *line);
-			/* Only append the new line if this isn't the last line in the file */
-			if (*(line+1))
-				g_string_append_c (new_contents, '\n');
+		regex = g_regex_new ("^127\\.0\\.0\\.2\\s+.+$", G_REGEX_MULTILINE, 0, NULL);
+		new_contents = g_regex_replace (regex, contents, contents_len, 0, replacement->str, 0, &error);
+
+		g_free (contents);
+		g_string_free (replacement, TRUE);
+		g_regex_unref (regex);
+
+		if (!error && g_file_set_contents (hosts, new_contents, -1, &error))
+			success = TRUE;
+		else {
+			nm_warning ("%s: couldn't update %s: (%d) %s",
+						__func__, hosts, error ? error->code : 0,
+						(error && error->message) ? error->message : "(unknown)");
+			if (error)
+				g_error_free (error);
 		}
-	}
 
-	/* Hmm, /etc/hosts was empty for some reason */
-	if (!added) {
-		g_string_append (new_contents, "# Do not remove the following line, or various programs");
-		g_string_append (new_contents, "# that require network functionality will fail.");
-		g_string_append (new_contents, "127.0.0.1\t" FALLBACK_HOSTNAME "\tlocalhost");
+		g_free (new_contents);
 	}
 
-	error = NULL;
-	if (!g_file_set_contents (SYSCONFDIR "/hosts", new_contents->str, -1, &error)) {
-		nm_warning ("%s: couldn't update " SYSCONFDIR "/hosts: (%d) %s",
-		            __func__, error ? error->code : 0,
-		            (error && error->message) ? error->message : "(unknown)");
-		if (error)
-			g_error_free (error);
-	} else
-		success = TRUE;
-
-	g_string_free (new_contents, TRUE);
 	return success;
 }
 
@@ -336,7 +306,13 @@ set_system_hostname (const char *new_hostname, const char *msg)
 {
 	char old_hostname[HOST_NAME_MAX + 1];
 	int ret = 0;
-	const char *name = new_hostname ? new_hostname : FALLBACK_HOSTNAME;
+	char **strv;
+	const char *name;
+	const char *domain;
+
+	strv = g_strsplit (new_hostname ? new_hostname : FALLBACK_HOSTNAME, ".", 2);
+	name = strv[0];
+	domain = strv[1];
 
 	old_hostname[HOST_NAME_MAX] = '\0';
 	errno = 0;
@@ -346,16 +322,15 @@ set_system_hostname (const char *new_hostname, const char *msg)
 		            __func__, errno, strerror (errno));
 	} else {
 		/* Do nothing if the hostname isn't actually changing */
-		if (   (new_hostname && !strcmp (old_hostname, new_hostname))
-		    || (!new_hostname && !strcmp (old_hostname, FALLBACK_HOSTNAME)))
-			return;
+		if (!strcmp (old_hostname, name))
+			goto out;
 	}
 
 	nm_info ("Setting system hostname to '%s' (%s)", name, msg);
 
 	ret = sethostname (name, strlen (name));
 	if (ret == 0) {
-		if (!update_etc_hosts (name)) {
+		if (!update_etc_hosts (name, domain)) {
 			/* error updating /etc/hosts; fallback to localhost.localdomain */
 			nm_info ("Setting system hostname to '" FALLBACK_HOSTNAME "' (error updating /etc/hosts)");
 			ret = sethostname (FALLBACK_HOSTNAME, strlen (FALLBACK_HOSTNAME));
@@ -369,6 +344,9 @@ set_system_hostname (const char *new_hostname, const char *msg)
 		nm_warning ("%s: couldn't set the system hostname to '%s': (%d) %s",
 		            __func__, name, errno, strerror (errno));
 	}
+
+ out:
+	g_strfreev (strv);
 }
 
 static void
-- 
1.6.0.2

