hostnamed: introduce systemd-hostnamed

http://www.freedesktop.org/wiki/Software/systemd/hostnamed
This commit is contained in:
Lennart Poettering 2011-04-16 02:02:54 +02:00
parent 25e3655a00
commit 7640a5de1b
16 changed files with 1099 additions and 16 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
systemd-hostnamed
systemd-binfmt
systemd-getty-generator
systemd-nspawn

View File

@ -144,7 +144,8 @@ rootlibexec_PROGRAMS = \
systemd-ac-power \
systemd-detect-virt \
systemd-sysctl \
systemd-binfmt
systemd-binfmt \
systemd-hostnamed
systemgenerator_PROGRAMS = \
systemd-getty-generator
@ -177,10 +178,12 @@ dist_pkgsysconf_DATA = \
src/system.conf
dist_dbuspolicy_DATA = \
src/org.freedesktop.systemd1.conf
src/org.freedesktop.systemd1.conf \
src/org.freedesktop.hostname1.conf
dist_dbussystemservice_DATA = \
src/org.freedesktop.systemd1.service
src/org.freedesktop.systemd1.service \
src/org.freedesktop.hostname1.service
dist_udevrules_DATA = \
src/99-systemd.rules
@ -282,6 +285,7 @@ nodist_systemunit_DATA = \
units/systemd-initctl.service \
units/systemd-logger.service \
units/systemd-shutdownd.service \
units/systemd-hostnamed.service \
units/systemd-kmsg-syslogd.service \
units/systemd-modules-load.service \
units/systemd-vconsole-setup.service \
@ -326,6 +330,7 @@ EXTRA_DIST = \
units/systemd-initctl.service.in \
units/systemd-logger.service.in \
units/systemd-shutdownd.service.in \
units/systemd-hostnamed.service.in \
units/systemd-kmsg-syslogd.service.in \
units/systemd-modules-load.service.in \
units/systemd-vconsole-setup.service.in \
@ -406,9 +411,12 @@ dist_doc_DATA = \
pkgconfigdata_DATA = \
systemd.pc
polkitpolicy_DATA = \
nodist_polkitpolicy_DATA = \
src/org.freedesktop.systemd1.policy
dist_polkitpolicy_DATA = \
src/org.freedesktop.hostname1.policy
noinst_LTLIBRARIES = \
libsystemd-basic.la \
libsystemd-core.la \
@ -571,6 +579,7 @@ MANPAGES = \
man/vconsole.conf.5 \
man/locale.conf.5 \
man/os-release.5 \
man/machine-info.5 \
man/modules-load.d.5 \
man/binfmt.d.5 \
man/sysctl.d.5 \
@ -754,6 +763,19 @@ systemd_shutdownd_LDADD = \
libsystemd-basic.la \
libsystemd-daemon.la
systemd_hostnamed_SOURCES = \
src/hostnamed.c \
src/dbus-common.c
systemd_hostnamed_CFLAGS = \
$(AM_CFLAGS) \
$(DBUS_CFLAGS)
systemd_hostnamed_LDADD = \
libsystemd-basic.la \
libsystemd-daemon.la \
$(DBUS_LIBS)
systemd_shutdown_SOURCES = \
src/mount-setup.c \
src/umount.c \
@ -1346,9 +1368,10 @@ install-data-hook:
$(LN_S) graphical.target runlevel5.target && \
$(LN_S) reboot.target runlevel6.target )
( cd $(DESTDIR)$(systemunitdir) && \
rm -f default.target ctrl-alt-del.target && \
rm -f default.target ctrl-alt-del.target dbus-org.freedesktop.hostname1.service && \
$(LN_S) graphical.target default.target && \
$(LN_S) reboot.target ctrl-alt-del.target )
$(LN_S) reboot.target ctrl-alt-del.target && \
$(LN_S) systemd-hostnamed.service dbus-org.freedesktop.hostname1.service )
( cd $(DESTDIR)$(systemunitdir)/multi-user.target.wants && \
rm -f getty.target systemd-user-sessions.service systemd-ask-password-wall.path && \
$(LN_S) ../getty.target getty.target && \

View File

@ -44,7 +44,7 @@
<refnamediv>
<refname>hostname</refname>
<refpurpose>local host name configuration file</refpurpose>
<refpurpose>Local host name configuration file</refpurpose>
</refnamediv>
<refsynopsisdiv>
@ -62,10 +62,10 @@
newline-terminated host name string. The
host name may be a free-form string up to 64 characters
in length, however it is recommended that it consists
only of 7bit ASCII characters and no spaces or dots,
and limit itself to the format allowed for DNS domain
only of 7bit 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
requirement.</para>
strict requirement.</para>
<para>Depending on the operating system other
configuration files might be checked for configuration
@ -85,7 +85,10 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sethostname</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>

View File

@ -76,7 +76,7 @@
with a globally unique ID in the network, that does
not change even if the local network configuration
changes. Due to this and its greater length it is
a more useful replacement than the
a more useful replacement for the
<citerefentry><refentrytitle>gethostid</refentrytitle><manvolnum>3</manvolnum></citerefentry>
call POSIX specifies.</para>
</refsect1>
@ -97,7 +97,9 @@
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>gethostid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>

147
man/machine-info.xml Normal file
View File

@ -0,0 +1,147 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<?xml-stylesheet type="text/xsl" href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!--
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
-->
<refentry id="machine-info">
<refentryinfo>
<title>machine-info</title>
<productname>systemd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Lennart</firstname>
<surname>Poettering</surname>
<email>lennart@poettering.net</email>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>machine-info</refentrytitle>
<manvolnum>5</manvolnum>
</refmeta>
<refnamediv>
<refname>machine-info</refname>
<refpurpose>Local machine information file</refpurpose>
</refnamediv>
<refsynopsisdiv>
<para><filename>/etc/machine-info</filename></para>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>The <filename>/etc/machine-info</filename> file
contains machine meta data.</para>
<para>The basic file format of
<filename>machine-info</filename> is a
newline-separated list of environment-like
shell-compatible variable assignments. It is possible
to source the configuration from shell scripts,
however, beyond mere variable assignments no shell
features are supported, allowing applications to read
the file without implementing a shell compatible
execution engine.</para>
<para><filename>/etc/machine-info</filename> contains
meta data about the machine that is set by the user or
administrator.</para>
<para>Depending on the operating system other
configuration files might be checked for machine
information as well, however only as fallback.</para>
</refsect1>
<refsect1>
<title>Options</title>
<para>The following machine meta data parameters may
be set using
<filename>/etc/machine-info</filename>:</para>
<variablelist>
<varlistentry>
<term><varname>PRETTY_HOSTNAME=</varname></term>
<listitem><para>A pretty
human-readable UTF8 machine identifier
string. This should contain a name
like <literal>Lennart's
Laptop</literal> which is useful to
present to the user and does not
suffer by the syntax limitations of
internet domain names. If possible the
internet host name as configured in
<filename>/etc/hostname</filename>
should be kept similar to this
one. Example: if this value is
<literal>Lennart's Computer</literal>
an Internet host name of
<literal>lennarts-computer</literal>
might be a good choice. If this
parameter is not set an application
should fall back to the Internet host
name for presentation
purposes.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>ICON_NAME=</varname></term>
<listitem><para>An icon identifying
this machine according to the <ulink
url="http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html">XDG
Icon Naming Specification</ulink>. If
this parameter is not set an
application should fall back to
<literal>computer</literal> or a
similar icon name.</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Example</title>
<programlisting>PRETTY_NAME="Lennart's Computer"
ICON_NAME=computer-laptop</programlisting>
</refsect1>
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>os-release</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -182,10 +182,10 @@
<title>Example</title>
<programlisting>NAME=Fedora
VERSION=15 (Rawhide)
VERSION="15 (Rawhide)"
ID=fedora
VERSION_ID=15
PRETTY_NAME=Fedora 15 (Rawhide)
PRETTY_NAME="Fedora 15 (Rawhide)"
ANSI_COLOR=0;34</programlisting>
</refsect1>
@ -193,7 +193,10 @@ ANSI_COLOR=0;34</programlisting>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>lsb_release</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<citerefentry><refentrytitle>lsb_release</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>hostname</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-id</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
<citerefentry><refentrytitle>machine-info</refentrytitle><manvolnum>5</manvolnum></citerefentry>
</para>
</refsect1>

689
src/hostnamed.c Normal file
View File

@ -0,0 +1,689 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <dbus/dbus.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
#include "strv.h"
#include "dbus-common.h"
#define INTROSPECTION \
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
"<node>\n" \
" <interface name=\"org.freedesktop.hostname1\">\n" \
" <property name=\"Hostname\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"StaticHostname\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"PrettyHostname\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"IconName\" type=\"s\" access=\"read\"/>\n" \
" <method name=\"SetHostname\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"SetStaticHostname\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"SetPrettyHostname\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
" <method name=\"SetIconName\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
" </interface>\n" \
BUS_PROPERTIES_INTERFACE \
BUS_INTROSPECTABLE_INTERFACE \
BUS_PEER_INTERFACE \
"</node>\n"
#define INTERFACES_LIST \
BUS_GENERIC_INTERFACES_LIST \
"org.freedesktop.hostname1\0"
enum {
PROP_HOSTNAME,
PROP_STATIC_HOSTNAME,
PROP_PRETTY_HOSTNAME,
PROP_ICON_NAME,
_PROP_MAX
};
static char *data[_PROP_MAX] = {
NULL,
NULL,
NULL,
NULL
};
static void free_data(void) {
int p;
for (p = 0; p < _PROP_MAX; p++) {
free(data[p]);
data[p] = NULL;
}
}
static int read_data(void) {
int r;
free_data();
data[PROP_HOSTNAME] = gethostname_malloc();
if (!data[PROP_HOSTNAME])
return -ENOMEM;
r = read_one_line_file("/etc/hostname", &data[PROP_STATIC_HOSTNAME]);
if (r < 0 && r != -ENOENT)
return r;
r = parse_env_file("/etc/machine-info", NEWLINE,
"PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME],
"ICON_NAME", &data[PROP_ICON_NAME],
NULL);
if (r < 0 && r != -ENOENT)
return r;
return 0;
}
static const char* fallback_icon_name(void) {
#if defined(__i386__) || defined(__x86_64__)
int r;
char *type;
unsigned t;
#endif
if (detect_virtualization(NULL) > 0)
return "computer-vm";
#if defined(__i386__) || defined(__x86_64__)
r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
if (r < 0)
return NULL;
r = safe_atou(type, &t);
free(type);
if (r < 0)
return NULL;
/* We only list the really obvious cases here. The DMI data is
unreliable enough, so let's not do any additional guesswork
on top of that. */
switch (t) {
case 0x3:
case 0x4:
case 0x6:
case 0x7:
return "computer-desktop";
case 0x9:
case 0xA:
case 0xE:
return "computer-laptop";
case 0x11:
return "computer-server";
}
#endif
return NULL;
}
static int write_data_hostname(void) {
const char *hn;
if (isempty(data[PROP_HOSTNAME]))
hn = "localhost";
else
hn = data[PROP_HOSTNAME];
if (sethostname(hn, strlen(hn)) < 0)
return -errno;
return 0;
}
static int write_data_static_hostname(void) {
if (isempty(data[PROP_STATIC_HOSTNAME])) {
if (unlink("/etc/hostname") < 0)
return errno == ENOENT ? 0 : -errno;
return 0;
}
return write_one_line_file("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
}
static int write_data_other(void) {
static const char * const name[_PROP_MAX] = {
[PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
[PROP_ICON_NAME] = "ICON_NAME"
};
char **l = NULL;
int r, p;
r = load_env_file("/etc/machine-info", &l);
if (r < 0 && r != -ENOENT)
return r;
for (p = 2; p < _PROP_MAX; p++) {
char *t, **u;
assert(name[p]);
if (isempty(data[p])) {
l = strv_env_unset(l, name[p]);
continue;
}
if (asprintf(&t, "%s=%s", name[p], strempty(data[p])) < 0) {
strv_free(l);
return -ENOMEM;
}
u = strv_env_set(l, t);
free(t);
strv_free(l);
if (!u)
return -ENOMEM;
l = u;
}
if (strv_isempty(l)) {
if (unlink("/etc/machine-info") < 0)
return errno == ENOENT ? 0 : -errno;
return 0;
}
r = write_env_file("/etc/machine-info", l);
strv_free(l);
return r;
}
/* This mimics dbus_bus_get_unix_user() */
static pid_t get_unix_process_id(
DBusConnection *connection,
const char *name,
DBusError *error) {
DBusMessage *m = NULL, *reply = NULL;
uint32_t pid = 0;
m = dbus_message_new_method_call(
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS,
"GetConnectionUnixProcessID");
if (!m) {
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
goto finish;
}
if (!dbus_message_append_args(
m,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID)) {
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
goto finish;
}
reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
if (!reply)
goto finish;
if (dbus_set_error_from_message(error, reply))
goto finish;
if (!dbus_message_get_args(
reply, error,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
goto finish;
finish:
if (m)
dbus_message_unref(m);
if (reply)
dbus_message_unref(reply);
return (pid_t) pid;
}
static int verify_polkit(
DBusConnection *c,
DBusMessage *request,
const char *action,
bool interactive,
DBusError *error) {
DBusMessage *m = NULL, *reply = NULL;
const char *unix_process = "unix-process", *pid = "pid", *starttime = "start-time", *cancel_id = "";
const char *sender;
uint32_t flags = interactive ? 1 : 0;
pid_t pid_raw;
uint32_t pid_u32;
unsigned long long starttime_raw;
uint64_t starttime_u64;
DBusMessageIter iter_msg, iter_struct, iter_array, iter_dict, iter_variant;
int r;
dbus_bool_t authorized = FALSE;
assert(c);
assert(request);
sender = dbus_message_get_sender(request);
if (!sender)
return -EINVAL;
pid_raw = get_unix_process_id(c, sender, error);
if (pid_raw == 0)
return -EINVAL;
r = get_starttime_of_pid(pid_raw, &starttime_raw);
if (r < 0)
return r;
m = dbus_message_new_method_call(
"org.freedesktop.PolicyKit1",
"/org/freedesktop/PolicyKit1/Authority",
"org.freedesktop.PolicyKit1.Authority",
"CheckAuthorization");
if (!m)
return -ENOMEM;
dbus_message_iter_init_append(m, &iter_msg);
pid_u32 = (uint32_t) pid_raw;
starttime_u64 = (uint64_t) starttime_raw;
if (!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_STRUCT, NULL, &iter_struct) ||
!dbus_message_iter_append_basic(&iter_struct, DBUS_TYPE_STRING, &unix_process) ||
!dbus_message_iter_open_container(&iter_struct, DBUS_TYPE_ARRAY, "{sv}", &iter_array) ||
!dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
!dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &pid) ||
!dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "u", &iter_variant) ||
!dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT32, &pid_u32) ||
!dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
!dbus_message_iter_close_container(&iter_array, &iter_dict) ||
!dbus_message_iter_open_container(&iter_array, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict) ||
!dbus_message_iter_append_basic(&iter_dict, DBUS_TYPE_STRING, &starttime) ||
!dbus_message_iter_open_container(&iter_dict, DBUS_TYPE_VARIANT, "t", &iter_variant) ||
!dbus_message_iter_append_basic(&iter_variant, DBUS_TYPE_UINT64, &starttime_u64) ||
!dbus_message_iter_close_container(&iter_dict, &iter_variant) ||
!dbus_message_iter_close_container(&iter_array, &iter_dict) ||
!dbus_message_iter_close_container(&iter_struct, &iter_array) ||
!dbus_message_iter_close_container(&iter_msg, &iter_struct) ||
!dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &action) ||
!dbus_message_iter_open_container(&iter_msg, DBUS_TYPE_ARRAY, "{ss}", &iter_array) ||
!dbus_message_iter_close_container(&iter_msg, &iter_array) ||
!dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_UINT32, &flags) ||
!dbus_message_iter_append_basic(&iter_msg, DBUS_TYPE_STRING, &cancel_id)) {
r = -ENOMEM;
goto finish;
}
reply = dbus_connection_send_with_reply_and_block(c, m, -1, error);
if (!reply) {
r = -EIO;
goto finish;
}
if (dbus_set_error_from_message(error, reply)) {
r = -EIO;
goto finish;
}
if (!dbus_message_iter_init(reply, &iter_msg) ||
dbus_message_iter_get_arg_type(&iter_msg) != DBUS_TYPE_STRUCT) {
r = -EIO;
goto finish;
}
dbus_message_iter_recurse(&iter_msg, &iter_struct);
if (dbus_message_iter_get_arg_type(&iter_struct) != DBUS_TYPE_BOOLEAN) {
r = -EIO;
goto finish;
}
dbus_message_iter_get_basic(&iter_struct, &authorized);
r = authorized ? 0 : -EPERM;
finish:
if (m)
dbus_message_unref(m);
if (reply)
dbus_message_unref(reply);
return r;
}
static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) {
const char *name;
assert(i);
assert(property);
if (isempty(data[PROP_ICON_NAME]))
name = fallback_icon_name();
else
name = data[PROP_ICON_NAME];
return bus_property_append_string(i, property, (void*) name);
}
static DBusHandlerResult hostname_message_handler(
DBusConnection *connection,
DBusMessage *message,
void *userdata) {
const BusProperty properties[] = {
{ "org.freedesktop.hostname1", "Hostname", bus_property_append_string, "s", data[PROP_HOSTNAME]},
{ "org.freedesktop.hostname1", "StaticHostname", bus_property_append_string, "s", data[PROP_STATIC_HOSTNAME]},
{ "org.freedesktop.hostname1", "PrettyHostname", bus_property_append_string, "s", data[PROP_PRETTY_HOSTNAME]},
{ "org.freedesktop.hostname1", "IconName", bus_hostname_append_icon_name, "s", data[PROP_ICON_NAME]},
{ NULL, NULL, NULL, NULL, NULL }
};
DBusMessage *reply = NULL, *changed = NULL;
DBusError error;
int r;
assert(connection);
assert(message);
dbus_error_init(&error);
if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetHostname")) {
const char *name;
dbus_bool_t interactive;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (isempty(name))
name = data[PROP_STATIC_HOSTNAME];
if (isempty(name))
name = "localhost";
if (!hostname_is_valid(name))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
if (!streq_ptr(name, data[PROP_HOSTNAME])) {
char *h;
r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-hostname", interactive, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
h = strdup(name);
if (!h)
goto oom;
free(data[PROP_HOSTNAME]);
data[PROP_HOSTNAME] = h;
r = write_data_hostname();
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
log_info("Changed host name to '%s'", data[PROP_HOSTNAME]);
changed = bus_properties_changed_new(
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
"Hostname\0");
if (!changed)
goto oom;
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetStaticHostname")) {
const char *name;
dbus_bool_t interactive;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (isempty(name))
name = NULL;
if (!streq_ptr(name, data[PROP_STATIC_HOSTNAME])) {
r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-static-hostname", interactive, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
if (isempty(name)) {
free(data[PROP_STATIC_HOSTNAME]);
data[PROP_STATIC_HOSTNAME] = NULL;
} else {
char *h;
if (!hostname_is_valid(name))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
h = strdup(name);
if (!h)
goto oom;
free(data[PROP_STATIC_HOSTNAME]);
data[PROP_STATIC_HOSTNAME] = h;
}
r = write_data_static_hostname();
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
log_info("Changed static host name to '%s'", data[PROP_HOSTNAME]);
changed = bus_properties_changed_new(
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
"StaticHostname\0");
if (!changed)
goto oom;
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") ||
dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) {
const char *name;
dbus_bool_t interactive;
int k;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (isempty(name))
name = NULL;
k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME;
if (!streq_ptr(name, data[k])) {
r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-machine-info", interactive, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
if (isempty(name)) {
free(data[k]);
data[k] = NULL;
} else {
char *h;
h = strdup(name);
if (!h)
goto oom;
free(data[k]);
data[k] = h;
}
r = write_data_other();
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", data[k]);
changed = bus_properties_changed_new(
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0");
if (!changed)
goto oom;
}
} else
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, properties);
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
if (!dbus_connection_send(connection, reply, NULL))
goto oom;
dbus_message_unref(reply);
reply = NULL;
if (changed) {
if (!dbus_connection_send(connection, changed, NULL))
goto oom;
dbus_message_unref(changed);
}
return DBUS_HANDLER_RESULT_HANDLED;
oom:
if (reply)
dbus_message_unref(reply);
if (changed)
dbus_message_unref(changed);
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
int main(int argc, char *argv[]) {
const DBusObjectPathVTable hostname_vtable = {
.message_function = hostname_message_handler
};
DBusConnection *bus = NULL;
DBusError error;
int r;
dbus_error_init(&error);
log_set_target(LOG_TARGET_AUTO);
log_parse_environment();
log_open();
if (argc != 1) {
log_error("This program takes no arguments.");
r = -EINVAL;
goto finish;
}
umask(0022);
r = read_data();
if (r < 0) {
log_error("Failed to read hostname data: %s", strerror(-r));
goto finish;
}
bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
if (!bus) {
log_error("Failed to get system D-Bus connection: %s", error.message);
r = -ECONNREFUSED;
goto finish;
}
if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL)) {
log_error("Not enough memory");
r = -ENOMEM;
goto finish;
}
if (dbus_bus_request_name(bus, "org.freedesktop.hostname1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) < 0) {
log_error("Failed to register name on bus: %s", error.message);
goto finish;
}
while (dbus_connection_read_write_dispatch(bus, -1))
;
r = 0;
finish:
free_data();
if (bus) {
dbus_connection_flush(bus);
dbus_connection_close(bus);
dbus_connection_unref(bus);
}
dbus_error_free(&error);
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<!--
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-->
<busconfig>
<policy user="root">
<allow own="org.freedesktop.hostname1"/>
<allow send_destination="org.freedesktop.hostname1"/>
<allow receive_sender="org.freedesktop.hostname1"/>
</policy>
<policy context="default">
<allow send_destination="org.freedesktop.hostname1"/>
<allow receive_sender="org.freedesktop.hostname1"/>
</policy>
</busconfig>

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?> <!--*-nxml-*-->
<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
<!--
This file is part of systemd.
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-->
<policyconfig>
<vendor>The systemd Project</vendor>
<vendor_url>http://www.freedesktop.org/wiki/Software/systemd</vendor_url>
<action id="org.freedesktop.hostname1.set-hostname">
<description>Set host name</description>
<message>Authentication is required to set the local host name.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.hostname1.set-static-hostname">
<description>Set static host name</description>
<message>Authentication is required to set the statically configured local host name.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
<action id="org.freedesktop.hostname1.set-machine-info">
<description>Set machine information</description>
<message>Authentication is required to set local machine information.</message>
<defaults>
<allow_any>auth_admin_keep</allow_any>
<allow_inactive>auth_admin_keep</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>

View File

@ -0,0 +1,12 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
[D-BUS Service]
Name=org.freedesktop.hostname1
Exec=/bin/false
User=root
SystemdService=dbus-org.freedesktop.hostname1.service

View File

@ -525,6 +525,32 @@ char **strv_env_delete(char **x, unsigned n_lists, ...) {
return r;
}
char **strv_env_unset(char **l, const char *p) {
char **f, **t;
if (!l)
return NULL;
assert(p);
/* Drops every occurrence of the env var setting p in the
* string list. edits in-place. */
for (f = t = l; *f; f++) {
if (env_match(*f, p)) {
free(*f);
continue;
}
*(t++) = *f;
}
*t = NULL;
return l;
}
char **strv_env_set(char **x, const char *p) {
char **k, **r;

View File

@ -59,6 +59,7 @@ char **strv_env_merge(unsigned n_lists, ...);
char **strv_env_delete(char **x, unsigned n_lists, ...);
char **strv_env_set(char **x, const char *p);
char **strv_env_unset(char **l, const char *p);
char *strv_env_get_with_length(char **l, const char *name, size_t k);
char *strv_env_get(char **x, const char *n);

View File

@ -496,6 +496,64 @@ int get_parent_of_pid(pid_t pid, pid_t *_ppid) {
return 0;
}
int get_starttime_of_pid(pid_t pid, unsigned long long *st) {
int r;
FILE *f;
char fn[PATH_MAX], line[LINE_MAX], *p;
assert(pid > 0);
assert(st);
assert_se(snprintf(fn, sizeof(fn)-1, "/proc/%lu/stat", (unsigned long) pid) < (int) (sizeof(fn)-1));
char_array_0(fn);
if (!(f = fopen(fn, "r")))
return -errno;
if (!(fgets(line, sizeof(line), f))) {
r = -errno;
fclose(f);
return r;
}
fclose(f);
/* Let's skip the pid and comm fields. The latter is enclosed
* in () but does not escape any () in its value, so let's
* skip over it manually */
if (!(p = strrchr(line, ')')))
return -EIO;
p++;
if (sscanf(p, " "
"%*c " /* state */
"%*d " /* ppid */
"%*d " /* pgrp */
"%*d " /* session */
"%*d " /* tty_nr */
"%*d " /* tpgid */
"%*u " /* flags */
"%*u " /* minflt */
"%*u " /* cminflt */
"%*u " /* majflt */
"%*u " /* cmajflt */
"%*u " /* utime */
"%*u " /* stime */
"%*d " /* cutime */
"%*d " /* cstime */
"%*d " /* priority */
"%*d " /* nice */
"%*d " /* num_threads */
"%*d " /* itrealvalue */
"%llu " /* starttime */,
st) != 1)
return -EIO;
return 0;
}
int write_one_line_file(const char *fn, const char *line) {
FILE *f;
int r;
@ -776,6 +834,29 @@ finish:
return r;
}
int write_env_file(const char *fname, char **l) {
char **i;
FILE *f;
int r;
f = fopen(fname, "we");
if (!f)
return -errno;
STRV_FOREACH(i, l) {
fputs(*i, f);
fputc('\n', f);
}
fflush(f);
r = ferror(f) ? -errno : 0;
fclose(f);
return r;
}
char *truncate_nl(char *s) {
assert(s);

View File

@ -196,6 +196,7 @@ char *split_quoted(const char *c, size_t *l, char **state);
char **split_path_and_make_absolute(const char *p);
pid_t get_parent_of_pid(pid_t pid, pid_t *ppid);
int get_starttime_of_pid(pid_t pid, unsigned long long *st);
int write_one_line_file(const char *fn, const char *line);
int read_one_line_file(const char *fn, char **line);
@ -203,6 +204,7 @@ int read_full_file(const char *fn, char **contents);
int parse_env_file(const char *fname, const char *separator, ...) _sentinel_;
int load_env_file(const char *fname, char ***l);
int write_env_file(const char *fname, char **l);
char *strappend(const char *s, const char *suffix);
char *strnappend(const char *s, const char *suffix, size_t length);

1
units/.gitignore vendored
View File

@ -1,3 +1,4 @@
systemd-hostnamed.service
console-shell.service
systemd-sysctl.service
systemd-ask-password-console.service

View File

@ -0,0 +1,16 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# See systemd.special(7) for details
[Unit]
Description=Hostname Service
[Service]
ExecStart=@rootlibexecdir@/systemd-hostnamed
Type=dbus
BusName=org.freedesktop.hostname1