/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-***/
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "alloc-util.h"
+#include "bus-common-errors.h"
#include "bus-util.h"
#include "def.h"
#include "env-util.h"
#include "fileio-label.h"
+#include "fileio.h"
#include "hostname-util.h"
+#include "id128-util.h"
+#include "main-func.h"
+#include "os-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "selinux-util.h"
+#include "signal-util.h"
#include "strv.h"
#include "user-util.h"
#include "util.h"
typedef struct Context {
char *data[_PROP_MAX];
Hashmap *polkit_registry;
+ sd_id128_t uuid;
+ bool has_uuid;
} Context;
static void context_reset(Context *c) {
c->data[p] = mfree(c->data[p]);
}
-static void context_free(Context *c) {
+static void context_clear(Context *c) {
assert(c);
context_reset(c);
if (r < 0 && r != -ENOENT)
return r;
- r = parse_env_file("/etc/machine-info", NEWLINE,
+ r = parse_env_file(NULL, "/etc/machine-info",
"PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
"ICON_NAME", &c->data[PROP_ICON_NAME],
"CHASSIS", &c->data[PROP_CHASSIS],
"DEPLOYMENT", &c->data[PROP_DEPLOYMENT],
- "LOCATION", &c->data[PROP_LOCATION],
- NULL);
+ "LOCATION", &c->data[PROP_LOCATION]);
if (r < 0 && r != -ENOENT)
return r;
- r = parse_env_file("/etc/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- "HOME_URL", &c->data[PROP_HOME_URL],
- NULL);
- if (r == -ENOENT)
- r = parse_env_file("/usr/lib/os-release", NEWLINE,
- "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
- "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
- "HOME_URL", &c->data[PROP_HOME_URL],
- NULL);
-
+ r = parse_os_release(NULL,
+ "PRETTY_NAME", &c->data[PROP_OS_PRETTY_NAME],
+ "CPE_NAME", &c->data[PROP_OS_CPE_NAME],
+ "HOME_URL", &c->data[PROP_HOME_URL],
+ NULL);
if (r < 0 && r != -ENOENT)
return r;
+ r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &c->uuid);
+ if (r < 0)
+ log_info_errno(r, "Failed to read product UUID, ignoring: %m");
+ c->has_uuid = (r >= 0);
+
return 0;
}
assert(c);
- r = load_env_file(NULL, "/etc/machine-info", NULL, &l);
+ r = load_env_file(NULL, "/etc/machine-info", &l);
if (r < 0 && r != -ENOENT)
return r;
return set_machine_info(userdata, m, PROP_LOCATION, method_set_location, error);
}
+static int method_get_product_uuid(sd_bus_message *m, void *userdata, sd_bus_error *error) {
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ Context *c = userdata;
+ int interactive, r;
+
+ assert(m);
+ assert(c);
+
+ if (!c->has_uuid)
+ return sd_bus_error_set(error, BUS_ERROR_NO_PRODUCT_UUID, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");
+
+ r = sd_bus_message_read(m, "b", &interactive);
+ if (r < 0)
+ return r;
+
+ r = bus_verify_polkit_async(
+ m,
+ CAP_SYS_ADMIN,
+ "org.freedesktop.hostname1.get-product-uuid",
+ NULL,
+ interactive,
+ UID_INVALID,
+ &c->polkit_registry,
+ error);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
+
+ r = sd_bus_message_new_method_return(m, &reply);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_append_array(reply, 'y', &c->uuid, sizeof(c->uuid));
+ if (r < 0)
+ return r;
+
+ return sd_bus_send(NULL, reply, NULL);
+}
+
static const sd_bus_vtable hostname_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Hostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetDeployment", "sb", NULL, method_set_deployment, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetLocation", "sb", NULL, method_set_location, SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD("GetProductUUID", "b", "ay", method_get_product_uuid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END,
};
return 0;
}
-int main(int argc, char *argv[]) {
- Context context = {};
+static int run(int argc, char *argv[]) {
+ _cleanup_(context_clear) Context context = {};
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r;
- log_set_target(LOG_TARGET_AUTO);
- log_parse_environment();
- log_open();
+ log_setup_service();
umask(0022);
mac_selinux_init();
if (argc != 1) {
log_error("This program takes no arguments.");
- r = -EINVAL;
- goto finish;
+ return -EINVAL;
}
+ assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
+
r = sd_event_default(&event);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate event loop: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate event loop: %m");
+
+ (void) sd_event_set_watchdog(event, true);
- sd_event_set_watchdog(event, true);
+ r = sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to install SIGINT handler: %m");
+
+ r = sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to install SIGTERM handler: %m");
r = connect_bus(&context, event, &bus);
if (r < 0)
- goto finish;
+ return r;
r = context_read_data(&context);
- if (r < 0) {
- log_error_errno(r, "Failed to read hostname and machine information: %m");
- goto finish;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to read hostname and machine information: %m");
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to run event loop: %m");
- goto finish;
- }
-
-finish:
- context_free(&context);
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);