summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martin.pitt@ubuntu.com>2015-05-19 07:49:56 +0200
committerLennart Poettering <lennart@poettering.net>2015-05-19 12:18:08 +0200
commit139e5336286c37d9d4a2df01931ba0a86abbac69 (patch)
tree3edcfb5098607cca83f3139260002e5a545152ae
parente861098bf22d8e65c3b2589e7ca056e720a06483 (diff)
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
-rw-r--r--man/hostname.xml11
-rw-r--r--src/core/hostname-setup.c24
-rw-r--r--src/hostname/hostnamed.c2
-rw-r--r--src/shared/hostname-util.c33
-rw-r--r--src/shared/hostname-util.h2
-rw-r--r--src/test/test-util.c47
6 files changed, 90 insertions, 29 deletions
diff --git a/man/hostname.xml b/man/hostname.xml
index 5d3d46d8ce..9688450e1c 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 217f201d05..932ddbf95a 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 ab9ddc706a..7ff3a4e224 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 2998fdf2c7..e336f269fa 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 f2821c3078..0c4763cf5a 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 9af3e757e3..36773c109d 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();