[systemd-commits] man/hostname.xml src/core src/hostname src/shared src/test

Lennart Poettering lennart at kemper.freedesktop.org
Tue May 19 03:18:16 PDT 2015


 man/hostname.xml           |   11 +++++-----
 src/core/hostname-setup.c  |   24 ----------------------
 src/hostname/hostnamed.c   |    2 -
 src/shared/hostname-util.c |   33 +++++++++++++++++++++++++++++++
 src/shared/hostname-util.h |    2 +
 src/test/test-util.c       |   47 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 90 insertions(+), 29 deletions(-)

New commits:
commit 139e5336286c37d9d4a2df01931ba0a86abbac69
Author: Martin Pitt <martin.pitt at ubuntu.com>
Date:   Tue May 19 07:49:56 2015 +0200

    hostname: Allow comments in /etc/hostname
    
    The hostname(1) tool allows comments in /etc/hostname. Introduce a new
    read_hostname_config() in hostname-util which reads a hostname configuration
    file like /etc/hostname, strips out comments, whitespace, and cleans the
    hostname. Use it in hostname-setup.c and hostnamed and remove duplicated code.
    
    Update hostname manpage. Add tests.
    
    https://launchpad.net/bugs/1053048

diff --git a/man/hostname.xml b/man/hostname.xml
index 5d3d46d..9688450 100644
--- a/man/hostname.xml
+++ b/man/hostname.xml
@@ -57,11 +57,12 @@
     name of the local system that is set during boot using the
     <citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
     system call. It should contain a single newline-terminated
-    hostname string. The hostname may be a free-form string up to 64
-    characters in length; however, it is recommended that it consists
-    only of 7-bit ASCII lower-case characters and no spaces or dots,
-    and limits itself to the format allowed for DNS domain name
-    labels, even though this is not a strict requirement.</para>
+    hostname string.  Comments (lines starting with a `#') are ignored.
+    The hostname may be a free-form string up to 64 characters in length;
+    however, it is recommended that it consists only of 7-bit ASCII lower-case
+    characters and no spaces or dots, and limits itself to the format allowed
+    for DNS domain name labels, even though this is not a strict
+    requirement.</para>
 
     <para>Depending on the operating system, other configuration files
     might be checked for configuration of the hostname as well,
diff --git a/src/core/hostname-setup.c b/src/core/hostname-setup.c
index 217f201..932ddbf 100644
--- a/src/core/hostname-setup.c
+++ b/src/core/hostname-setup.c
@@ -30,35 +30,13 @@
 #include "hostname-util.h"
 #include "hostname-setup.h"
 
-static int read_and_strip_hostname(const char *path, char **hn) {
-        char *s;
-        int r;
-
-        assert(path);
-        assert(hn);
-
-        r = read_one_line_file(path, &s);
-        if (r < 0)
-                return r;
-
-        hostname_cleanup(s, false);
-
-        if (isempty(s)) {
-                free(s);
-                return -ENOENT;
-        }
-
-        *hn = s;
-        return 0;
-}
-
 int hostname_setup(void) {
         int r;
         _cleanup_free_ char *b = NULL;
         const char *hn;
         bool enoent = false;
 
-        r = read_and_strip_hostname("/etc/hostname", &b);
+        r = read_hostname_config("/etc/hostname", &b);
         if (r < 0) {
                 if (r == -ENOENT)
                         enoent = true;
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index ab9ddc7..7ff3a4e 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -96,7 +96,7 @@ static int context_read_data(Context *c) {
         if (!c->data[PROP_HOSTNAME])
                 return -ENOMEM;
 
-        r = read_one_line_file("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]);
+        r = read_hostname_config("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]);
         if (r < 0 && r != -ENOENT)
                 return r;
 
diff --git a/src/shared/hostname-util.c b/src/shared/hostname-util.c
index 2998fdf..e336f26 100644
--- a/src/shared/hostname-util.c
+++ b/src/shared/hostname-util.c
@@ -158,3 +158,36 @@ int sethostname_idempotent(const char *s) {
 
         return 1;
 }
+
+int read_hostname_config(const char *path, char **hostname) {
+        _cleanup_fclose_ FILE *f = NULL;
+        char l[LINE_MAX];
+        char *name = NULL;
+
+        assert(path);
+        assert(hostname);
+
+        f = fopen(path, "re");
+        if (!f)
+                return -errno;
+
+        /* may have comments, ignore them */
+        FOREACH_LINE(l, f, return -errno) {
+                truncate_nl(l);
+                if (l[0] != '\0' && l[0] != '#') {
+                        /* found line with value */
+                        name = hostname_cleanup(l, false);
+                        name = strdup(name);
+                        if (!name)
+                                return -ENOMEM;
+                        break;
+                }
+        }
+
+        if (!name)
+                /* no non-empty line found */
+                return -ENOENT;
+
+        *hostname = name;
+        return 0;
+}
diff --git a/src/shared/hostname-util.h b/src/shared/hostname-util.h
index f2821c3..0c4763c 100644
--- a/src/shared/hostname-util.h
+++ b/src/shared/hostname-util.h
@@ -35,3 +35,5 @@ char* hostname_cleanup(char *s, bool lowercase);
 bool is_localhost(const char *hostname);
 
 int sethostname_idempotent(const char *s);
+
+int read_hostname_config(const char *path, char **hostname);
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9af3e75..36773c1 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -549,6 +549,52 @@ static void test_hostname_is_valid(void) {
         assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"));
 }
 
+static void test_read_hostname_config(void) {
+        char path[] = "/tmp/hostname.XXXXXX";
+        char *hostname;
+        int fd;
+
+        fd = mkostemp_safe(path, O_RDWR|O_CLOEXEC);
+        assert(fd > 0);
+        close(fd);
+
+        /* simple hostname */
+        write_string_file(path, "foo");
+        assert_se(read_hostname_config(path, &hostname) == 0);
+        assert_se(streq(hostname, "foo"));
+        free(hostname);
+
+        /* with comment */
+        write_string_file(path, "# comment\nfoo");
+        assert_se(read_hostname_config(path, &hostname) == 0);
+        assert_se(streq(hostname, "foo"));
+        free(hostname);
+
+        /* with comment and extra whitespace */
+        write_string_file(path, "# comment\n\n foo ");
+        assert_se(read_hostname_config(path, &hostname) == 0);
+        assert_se(streq(hostname, "foo"));
+        free(hostname);
+
+        /* cleans up name */
+        write_string_file(path, "!foo/bar.com");
+        assert_se(read_hostname_config(path, &hostname) == 0);
+        assert_se(streq(hostname, "foobar.com"));
+        free(hostname);
+
+        /* no value set */
+        hostname = (char*) 0x1234;
+        write_string_file(path, "# nothing here\n");
+        assert_se(read_hostname_config(path, &hostname) == -ENOENT);
+        assert_se(hostname == (char*) 0x1234);  /* does not touch argument on error */
+
+        /* nonexisting file */
+        assert_se(read_hostname_config("/non/existing", &hostname) == -ENOENT);
+        assert_se(hostname == (char*) 0x1234);  /* does not touch argument on error */
+
+        unlink(path);
+}
+
 static void test_u64log2(void) {
         assert_se(u64log2(0) == 0);
         assert_se(u64log2(8) == 3);
@@ -1481,6 +1527,7 @@ int main(int argc, char *argv[]) {
         test_foreach_word_quoted();
         test_memdup_multiply();
         test_hostname_is_valid();
+        test_read_hostname_config();
         test_u64log2();
         test_protect_errno();
         test_parse_size();



More information about the systemd-commits mailing list