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
This commit is contained in:
Martin Pitt 2015-05-19 07:49:56 +02:00 committed by Lennart Poettering
parent e861098bf2
commit 139e533628
6 changed files with 90 additions and 29 deletions

View File

@ -57,11 +57,12 @@
name of the local system that is set during boot using the name of the local system that is set during boot using the
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry> <citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>
system call. It should contain a single newline-terminated system call. It should contain a single newline-terminated
hostname string. The hostname may be a free-form string up to 64 hostname string. Comments (lines starting with a `#') are ignored.
characters in length; however, it is recommended that it consists The hostname may be a free-form string up to 64 characters in length;
only of 7-bit ASCII lower-case characters and no spaces or dots, however, it is recommended that it consists only of 7-bit ASCII lower-case
and limits itself to the format allowed for DNS domain name characters and no spaces or dots, and limits itself to the format allowed
labels, even though this is not a strict requirement.</para> for DNS domain name labels, even though this is not a strict
requirement.</para>
<para>Depending on the operating system, other configuration files <para>Depending on the operating system, other configuration files
might be checked for configuration of the hostname as well, might be checked for configuration of the hostname as well,

View File

@ -30,35 +30,13 @@
#include "hostname-util.h" #include "hostname-util.h"
#include "hostname-setup.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 hostname_setup(void) {
int r; int r;
_cleanup_free_ char *b = NULL; _cleanup_free_ char *b = NULL;
const char *hn; const char *hn;
bool enoent = false; bool enoent = false;
r = read_and_strip_hostname("/etc/hostname", &b); r = read_hostname_config("/etc/hostname", &b);
if (r < 0) { if (r < 0) {
if (r == -ENOENT) if (r == -ENOENT)
enoent = true; enoent = true;

View File

@ -96,7 +96,7 @@ static int context_read_data(Context *c) {
if (!c->data[PROP_HOSTNAME]) if (!c->data[PROP_HOSTNAME])
return -ENOMEM; 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) if (r < 0 && r != -ENOENT)
return r; return r;

View File

@ -158,3 +158,36 @@ int sethostname_idempotent(const char *s) {
return 1; 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;
}

View File

@ -35,3 +35,5 @@ char* hostname_cleanup(char *s, bool lowercase);
bool is_localhost(const char *hostname); bool is_localhost(const char *hostname);
int sethostname_idempotent(const char *s); int sethostname_idempotent(const char *s);
int read_hostname_config(const char *path, char **hostname);

View File

@ -549,6 +549,52 @@ static void test_hostname_is_valid(void) {
assert_se(!hostname_is_valid("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); 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) { static void test_u64log2(void) {
assert_se(u64log2(0) == 0); assert_se(u64log2(0) == 0);
assert_se(u64log2(8) == 3); assert_se(u64log2(8) == 3);
@ -1481,6 +1527,7 @@ int main(int argc, char *argv[]) {
test_foreach_word_quoted(); test_foreach_word_quoted();
test_memdup_multiply(); test_memdup_multiply();
test_hostname_is_valid(); test_hostname_is_valid();
test_read_hostname_config();
test_u64log2(); test_u64log2();
test_protect_errno(); test_protect_errno();
test_parse_size(); test_parse_size();