summaryrefslogtreecommitdiff
path: root/src/hostname/hostnamed.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-12-24 19:03:59 +0100
committerLennart Poettering <lennart@poettering.net>2012-12-24 19:03:59 +0100
commit7871c8e9327e4e5b18de9d8081b0f32fa38c2c1f (patch)
tree56dea3f21fcc707ac392696697a50d18c21a09d5 /src/hostname/hostnamed.c
parentf9ea108e7c3544c03822277a1112a48dc62f6ed4 (diff)
hostnamed: make chassis type configurable via /etc/machine-info
For many usecases it is useful to store the chassis type somewhere, and /etc/machine-info sounds like a good place. Ideally we could always detect the chassis type from firmware, but frequently that's not available and in many embedded devices probably entirely unrealistic. This patch adds a configurable setting CHASSIS= to /etc/machine-info and exposes this via hostnamectl/hostnamed. hostnamed will guess the chassis type from DMI if nothing is set explicitly. I also added support for detecting it from ACPI, which should be more useful as ACPI 5.0 actually knows a "tablet" chassis type, which neither DMI nor previous ACPI versions knew. This also enables DMI-based and ACPI-based detection for non-x86 systems as ACPI is apparently coming to ARM platforms soon. I tried to minimize the vocabulary of chassis types understood and added: desktop, laptop, server, tablet, handset. This is much less than either APCI or DMI know. If we need more types later on we can easily add them.
Diffstat (limited to 'src/hostname/hostnamed.c')
-rw-r--r--src/hostname/hostnamed.c141
1 files changed, 121 insertions, 20 deletions
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index cd3ef491ac..92b150bfc9 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -39,6 +39,7 @@
" <property name=\"StaticHostname\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"PrettyHostname\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"IconName\" type=\"s\" access=\"read\"/>\n" \
+ " <property name=\"Chassis\" 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" \
@@ -55,6 +56,10 @@
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"SetChassis\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
+ " </method>\n" \
" </interface>\n"
#define INTROSPECTION \
@@ -77,6 +82,7 @@ enum {
PROP_STATIC_HOSTNAME,
PROP_PRETTY_HOSTNAME,
PROP_ICON_NAME,
+ PROP_CHASSIS,
_PROP_MAX
};
@@ -84,6 +90,7 @@ static char *data[_PROP_MAX] = {
NULL,
NULL,
NULL,
+ NULL,
NULL
};
@@ -114,6 +121,7 @@ static int read_data(void) {
r = parse_env_file("/etc/machine-info", NEWLINE,
"PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME],
"ICON_NAME", &data[PROP_ICON_NAME],
+ "CHASSIS", &data[PROP_CHASSIS],
NULL);
if (r < 0 && r != -ENOENT)
return r;
@@ -122,10 +130,10 @@ static int read_data(void) {
}
static bool check_nss(void) {
-
void *dl;
- if ((dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY))) {
+ dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY);
+ if (dl) {
dlclose(dl);
return true;
}
@@ -133,25 +141,77 @@ static bool check_nss(void) {
return false;
}
-static const char* fallback_icon_name(void) {
+static bool valid_chassis(const char *chassis) {
-#if defined(__i386__) || defined(__x86_64__)
+ assert(chassis);
+
+ return nulstr_contains(
+ "vm\0"
+ "container\0"
+ "desktop\0"
+ "laptop\0"
+ "server\0"
+ "tablet\0"
+ "handset\0",
+ chassis);
+}
+
+static const char* fallback_chassis(void) {
int r;
char *type;
unsigned t;
-#endif
+ Virtualization v;
+
+ v = detect_virtualization(NULL);
+
+ if (v == VIRTUALIZATION_VM)
+ return "vm";
+ if (v == VIRTUALIZATION_CONTAINER)
+ return "container";
+
+ r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
+ if (r < 0)
+ goto try_dmi;
+
+ r = safe_atou(type, &t);
+ free(type);
+ if (r < 0)
+ goto try_dmi;
+
+ /* We only list the really obvious cases here as the ACPI data
+ * is not really super reliable.
+ *
+ * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
+ *
+ * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
+ */
+
+ switch(t) {
+
+ case 1:
+ case 3:
+ case 6:
+ return "desktop";
+
+ case 2:
+ return "laptop";
- if (detect_virtualization(NULL) > 0)
- return "computer-vm";
+ case 4:
+ case 5:
+ case 7:
+ return "server";
-#if defined(__i386__) || defined(__x86_64__)
+ case 8:
+ return "tablet";
+ }
+
+try_dmi:
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;
@@ -171,22 +231,38 @@ static const char* fallback_icon_name(void) {
case 0x4:
case 0x6:
case 0x7:
- return "computer-desktop";
+ return "desktop";
+ case 0x8:
case 0x9:
case 0xA:
case 0xE:
- return "computer-laptop";
+ return "laptop";
+
+ case 0xB:
+ return "handset";
case 0x11:
case 0x1C:
- return "computer-server";
+ return "server";
}
-#endif
return NULL;
}
+static char* fallback_icon_name(void) {
+ const char *chassis;
+
+ if (!isempty(data[PROP_CHASSIS]))
+ return strappend("computer-", data[PROP_CHASSIS]);
+
+ chassis = fallback_chassis();
+ if (chassis)
+ return strappend("computer-", chassis);
+
+ return strdup("computer");
+}
+
static int write_data_hostname(void) {
const char *hn;
@@ -218,7 +294,8 @@ static int write_data_other(void) {
static const char * const name[_PROP_MAX] = {
[PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
- [PROP_ICON_NAME] = "ICON_NAME"
+ [PROP_ICON_NAME] = "ICON_NAME",
+ [PROP_CHASSIS] = "CHASSIS"
};
char **l = NULL;
@@ -268,23 +345,39 @@ static int write_data_other(void) {
static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) {
const char *name;
+ _cleanup_free_ char *n = NULL;
assert(i);
assert(property);
if (isempty(data[PROP_ICON_NAME]))
- name = fallback_icon_name();
+ name = n = fallback_icon_name();
else
name = data[PROP_ICON_NAME];
return bus_property_append_string(i, property, (void*) name);
}
+static int bus_hostname_append_chassis(DBusMessageIter *i, const char *property, void *userdata) {
+ const char *name;
+
+ assert(i);
+ assert(property);
+
+ if (isempty(data[PROP_CHASSIS]))
+ name = fallback_chassis();
+ else
+ name = data[PROP_CHASSIS];
+
+ return bus_property_append_string(i, property, (void*) name);
+}
+
static const BusProperty bus_hostname_properties[] = {
{ "Hostname", bus_property_append_string, "s", sizeof(data[0])*PROP_HOSTNAME, true },
{ "StaticHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_STATIC_HOSTNAME, true },
{ "PrettyHostname", bus_property_append_string, "s", sizeof(data[0])*PROP_PRETTY_HOSTNAME, true },
{ "IconName", bus_hostname_append_icon_name, "s", sizeof(data[0])*PROP_ICON_NAME, true },
+ { "Chassis", bus_hostname_append_chassis, "s", sizeof(data[0])*PROP_CHASSIS, true },
{ NULL, }
};
@@ -414,7 +507,8 @@ static DBusHandlerResult hostname_message_handler(
}
} else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") ||
- dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) {
+ dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName") ||
+ dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetChassis")) {
const char *name;
dbus_bool_t interactive;
@@ -431,7 +525,8 @@ static DBusHandlerResult hostname_message_handler(
if (isempty(name))
name = NULL;
- k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME;
+ k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME :
+ streq(dbus_message_get_member(message), "SetChassis") ? PROP_CHASSIS : PROP_ICON_NAME;
if (!streq_ptr(name, data[k])) {
@@ -458,6 +553,8 @@ static DBusHandlerResult hostname_message_handler(
return bus_send_error_reply(connection, message, NULL, -EINVAL);
if (k == PROP_PRETTY_HOSTNAME && !string_is_safe(name))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
+ if (k == PROP_CHASSIS && !valid_chassis(name))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
h = strdup(name);
if (!h)
@@ -473,12 +570,15 @@ static DBusHandlerResult hostname_message_handler(
return bus_send_error_reply(connection, message, NULL, r);
}
- log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", strempty(data[k]));
+ log_info("Changed %s to '%s'",
+ k == PROP_PRETTY_HOSTNAME ? "pretty host name" :
+ k == PROP_CHASSIS ? "chassis" : "icon name", strempty(data[k]));
changed = bus_properties_changed_new(
"/org/freedesktop/hostname1",
"org.freedesktop.hostname1",
- k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0");
+ k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" :
+ k == PROP_CHASSIS ? "Chassis\0" : "IconName\0");
if (!changed)
goto oom;
}
@@ -486,7 +586,8 @@ static DBusHandlerResult hostname_message_handler(
} else
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
- if (!(reply = dbus_message_new_method_return(message)))
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
goto oom;
if (!dbus_connection_send(connection, reply, NULL))