Add %l as specifier for the hostname without any domain component

As described in #15603, it is a fairly common setup to use a fqdn as the
configured hostname. But it is often convenient to use just the actual
hostname, i.e. until the first dot. This adds support in tmpfiles, sysusers,
and unit files for %l which expands to that.

Fixes #15603.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-05-07 16:16:19 +02:00
parent eef4b80033
commit e97708fa3e
12 changed files with 72 additions and 14 deletions

View File

@ -24,6 +24,11 @@
<entry>Host name</entry>
<entry>The hostname of the running system.</entry>
</row>
<row id='l'>
<entry><literal>%l</literal></entry>
<entry>Short host name</entry>
<entry>The hostname of the running system, truncated at the first dot to remove any domain component.</entry>
</row>
<row id='m'>
<entry><literal>%m</literal></entry>
<entry>Machine ID</entry>

View File

@ -1747,6 +1747,11 @@ Note that this setting is <emphasis>not</emphasis> influenced by the <varname>Us
<entry>Host name</entry>
<entry>The hostname of the running system at the point in time the unit configuration is loaded.</entry>
</row>
<row>
<entry><literal>%l</literal></entry>
<entry>Short host name</entry>
<entry>The hostname of the running system at the point in time the unit configuration is loaded, truncated at the first dot to remove any domain component.</entry>
</row>
<row>
<entry><literal>%i</literal></entry>
<entry>Instance name</entry>

View File

@ -257,6 +257,7 @@ r - 500-900
<xi:include href="standard-specifiers.xml" xpointer="b"/>
<xi:include href="standard-specifiers.xml" xpointer="B"/>
<xi:include href="standard-specifiers.xml" xpointer="H"/>
<xi:include href="standard-specifiers.xml" xpointer="l"/>
<xi:include href="standard-specifiers.xml" xpointer="m"/>
<xi:include href="standard-specifiers.xml" xpointer="o"/>
<row>

View File

@ -646,6 +646,7 @@ w- /proc/sys/vm/swappiness - - - - 10</programlisting></para>
<entry>This is the home directory of the user running the command. In case of the system instance this resolves to <literal>/root</literal>.</entry>
</row>
<xi:include href="standard-specifiers.xml" xpointer="H"/>
<xi:include href="standard-specifiers.xml" xpointer="l"/>
<row>
<entry><literal>%L</literal></entry>
<entry>System or user log directory</entry>

View File

@ -31,6 +31,7 @@ bool hostname_is_set(void) {
char* gethostname_malloc(void) {
struct utsname u;
const char *s;
/* This call tries to return something useful, either the actual hostname
* or it makes something up. The only reason it might fail is OOM.
@ -38,10 +39,28 @@ char* gethostname_malloc(void) {
assert_se(uname(&u) >= 0);
if (isempty(u.nodename) || streq(u.nodename, "(none)"))
return strdup(FALLBACK_HOSTNAME);
s = u.nodename;
if (isempty(s) || streq(s, "(none)"))
s = FALLBACK_HOSTNAME;
return strdup(u.nodename);
return strdup(s);
}
char* gethostname_short_malloc(void) {
struct utsname u;
const char *s;
/* Like above, but kills the FQDN part if present. */
assert_se(uname(&u) >= 0);
s = u.nodename;
if (isempty(s) || streq(s, "(none)") || s[0] == '.') {
s = FALLBACK_HOSTNAME;
assert(s[0] != '.');
}
return strndup(s, strcspn(s, "."));
}
int gethostname_strict(char **ret) {

View File

@ -9,6 +9,7 @@
bool hostname_is_set(void);
char* gethostname_malloc(void);
char* gethostname_short_malloc(void);
int gethostname_strict(char **ret);
bool valid_ldh_char(char c) _const_;

View File

@ -291,6 +291,7 @@ int unit_full_printf(const Unit *u, const char *format, char **ret) {
{ 'm', specifier_machine_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'l', specifier_short_host_name, NULL },
{ 'b', specifier_boot_id, NULL },
{ 'v', specifier_kernel_release, NULL },
{}

View File

@ -160,6 +160,17 @@ int specifier_host_name(char specifier, const void *data, const void *userdata,
return 0;
}
int specifier_short_host_name(char specifier, const void *data, const void *userdata, char **ret) {
char *n;
n = gethostname_short_malloc();
if (!n)
return -ENOMEM;
*ret = n;
return 0;
}
int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret) {
struct utsname uts;
char *n;

View File

@ -18,6 +18,7 @@ int specifier_string(char specifier, const void *data, const void *userdata, cha
int specifier_machine_id(char specifier, const void *data, const void *userdata, char **ret);
int specifier_boot_id(char specifier, const void *data, const void *userdata, char **ret);
int specifier_host_name(char specifier, const void *data, const void *userdata, char **ret);
int specifier_short_host_name(char specifier, const void *data, const void *userdata, char **ret);
int specifier_kernel_release(char specifier, const void *data, const void *userdata, char **ret);
int specifier_architecture(char specifier, const void *data, const void *userdata, char **ret);
int specifier_os_id(char specifier, const void *data, const void *userdata, char **ret);

View File

@ -1389,17 +1389,18 @@ static bool item_equal(Item *a, Item *b) {
static int parse_line(const char *fname, unsigned line, const char *buffer) {
static const Specifier specifier_table[] = {
{ 'm', specifier_machine_id, NULL },
{ 'b', specifier_boot_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'v', specifier_kernel_release, NULL },
{ 'a', specifier_architecture, NULL },
{ 'o', specifier_os_id, NULL },
{ 'w', specifier_os_version_id, NULL },
{ 'B', specifier_os_build_id, NULL },
{ 'W', specifier_os_variant_id, NULL },
{ 'T', specifier_tmp_dir, NULL },
{ 'V', specifier_var_tmp_dir, NULL },
{ 'm', specifier_machine_id, NULL },
{ 'b', specifier_boot_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'l', specifier_short_host_name, NULL },
{ 'v', specifier_kernel_release, NULL },
{ 'a', specifier_architecture, NULL },
{ 'o', specifier_os_id, NULL },
{ 'w', specifier_os_version_id, NULL },
{ 'B', specifier_os_build_id, NULL },
{ 'W', specifier_os_variant_id, NULL },
{ 'T', specifier_tmp_dir, NULL },
{ 'V', specifier_var_tmp_dir, NULL },
{}
};

View File

@ -140,6 +140,16 @@ static void test_read_etc_hostname(void) {
unlink(path);
}
static void test_hostname_malloc(void) {
_cleanup_free_ char *h = NULL, *l = NULL;
assert_se(h = gethostname_malloc());
log_info("hostname_malloc: \"%s\"", h);
assert_se(l = gethostname_short_malloc());
log_info("hostname_short_malloc: \"%s\"", l);
}
static void test_fallback_hostname(void) {
if (!hostname_is_valid(FALLBACK_HOSTNAME, false)) {
log_error("Configured fallback hostname \"%s\" is not valid.", FALLBACK_HOSTNAME);
@ -154,6 +164,7 @@ int main(int argc, char *argv[]) {
test_hostname_is_valid();
test_hostname_cleanup();
test_read_etc_hostname();
test_hostname_malloc();
test_fallback_hostname();

View File

@ -184,6 +184,7 @@ static const Specifier specifier_table[] = {
{ 'm', specifier_machine_id_safe, NULL },
{ 'b', specifier_boot_id, NULL },
{ 'H', specifier_host_name, NULL },
{ 'l', specifier_short_host_name, NULL },
{ 'v', specifier_kernel_release, NULL },
{ 'a', specifier_architecture, NULL },
{ 'o', specifier_os_id, NULL },