1 /* SPDX-License-Identifier: LGPL-2.1+ */
4 #include <sys/utsname.h>
9 #include "alloc-util.h"
10 #include "bus-common-errors.h"
11 #include "bus-log-control-api.h"
12 #include "bus-polkit.h"
14 #include "env-file-label.h"
17 #include "fileio-label.h"
19 #include "hostname-util.h"
20 #include "id128-util.h"
21 #include "main-func.h"
22 #include "missing_capability.h"
23 #include "nscd-flush.h"
24 #include "nulstr-util.h"
26 #include "parse-util.h"
27 #include "path-util.h"
28 #include "selinux-util.h"
29 #include "service-util.h"
30 #include "signal-util.h"
32 #include "user-util.h"
36 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
52 typedef struct Context
{
53 char *data
[_PROP_MAX
];
54 Hashmap
*polkit_registry
;
57 static void context_reset(Context
*c
) {
62 for (p
= 0; p
< _PROP_MAX
; p
++)
63 c
->data
[p
] = mfree(c
->data
[p
]);
66 static void context_destroy(Context
*c
) {
70 bus_verify_polkit_async_registry_free(c
->polkit_registry
);
73 static int context_read_data(Context
*c
) {
80 c
->data
[PROP_HOSTNAME
] = gethostname_malloc();
81 if (!c
->data
[PROP_HOSTNAME
])
84 r
= read_etc_hostname(NULL
, &c
->data
[PROP_STATIC_HOSTNAME
]);
85 if (r
< 0 && r
!= -ENOENT
)
88 r
= parse_env_file(NULL
, "/etc/machine-info",
89 "PRETTY_HOSTNAME", &c
->data
[PROP_PRETTY_HOSTNAME
],
90 "ICON_NAME", &c
->data
[PROP_ICON_NAME
],
91 "CHASSIS", &c
->data
[PROP_CHASSIS
],
92 "DEPLOYMENT", &c
->data
[PROP_DEPLOYMENT
],
93 "LOCATION", &c
->data
[PROP_LOCATION
]);
94 if (r
< 0 && r
!= -ENOENT
)
97 r
= parse_os_release(NULL
,
98 "PRETTY_NAME", &c
->data
[PROP_OS_PRETTY_NAME
],
99 "CPE_NAME", &c
->data
[PROP_OS_CPE_NAME
],
100 "HOME_URL", &c
->data
[PROP_HOME_URL
],
102 if (r
< 0 && r
!= -ENOENT
)
108 static bool valid_chassis(const char *chassis
) {
111 return nulstr_contains(
125 static bool valid_deployment(const char *deployment
) {
128 return in_charset(deployment
, VALID_DEPLOYMENT_CHARS
);
131 static const char* fallback_chassis(void) {
136 v
= detect_virtualization();
137 if (VIRTUALIZATION_IS_VM(v
))
139 if (VIRTUALIZATION_IS_CONTAINER(v
))
142 r
= read_one_line_file("/sys/class/dmi/id/chassis_type", &type
);
146 r
= safe_atou(type
, &t
);
151 /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
152 additional guesswork on top of that.
154 See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here:
156 https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
161 case 0x3: /* Desktop */
162 case 0x4: /* Low Profile Desktop */
163 case 0x6: /* Mini Tower */
164 case 0x7: /* Tower */
167 case 0x8: /* Portable */
168 case 0x9: /* Laptop */
169 case 0xA: /* Notebook */
170 case 0xE: /* Sub Notebook */
173 case 0xB: /* Hand Held */
176 case 0x11: /* Main Server Chassis */
177 case 0x1C: /* Blade */
178 case 0x1D: /* Blade Enclosure */
181 case 0x1E: /* Tablet */
184 case 0x1F: /* Convertible */
185 case 0x20: /* Detachable */
186 return "convertible";
190 r
= read_one_line_file("/sys/firmware/acpi/pm_profile", &type
);
194 r
= safe_atou(type
, &t
);
199 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
201 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
203 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
208 case 1: /* Desktop */
209 case 3: /* Workstation */
210 case 6: /* Appliance PC */
216 case 4: /* Enterprise Server */
217 case 5: /* SOHO Server */
218 case 7: /* Performance Server */
228 static char* context_fallback_icon_name(Context
*c
) {
233 if (!isempty(c
->data
[PROP_CHASSIS
]))
234 return strjoin("computer-", c
->data
[PROP_CHASSIS
]);
236 chassis
= fallback_chassis();
238 return strjoin("computer-", chassis
);
240 return strdup("computer");
243 static bool hostname_is_useful(const char *hn
) {
244 return !isempty(hn
) && !is_localhost(hn
);
247 static int context_update_kernel_hostname(Context
*c
) {
248 const char *static_hn
;
253 static_hn
= c
->data
[PROP_STATIC_HOSTNAME
];
255 /* /etc/hostname with something other than "localhost"
256 * has the highest preference ... */
257 if (hostname_is_useful(static_hn
))
260 /* ... the transient hostname, (ie: DHCP) comes next ... */
261 else if (!isempty(c
->data
[PROP_HOSTNAME
]))
262 hn
= c
->data
[PROP_HOSTNAME
];
264 /* ... fallback to static "localhost.*" ignored above ... */
265 else if (!isempty(static_hn
))
268 /* ... and the ultimate fallback */
270 hn
= FALLBACK_HOSTNAME
;
272 if (sethostname_idempotent(hn
) < 0)
275 (void) nscd_flush_cache(STRV_MAKE("hosts"));
280 static int context_write_data_static_hostname(Context
*c
) {
284 if (isempty(c
->data
[PROP_STATIC_HOSTNAME
])) {
286 if (unlink("/etc/hostname") < 0)
287 return errno
== ENOENT
? 0 : -errno
;
291 return write_string_file_atomic_label("/etc/hostname", c
->data
[PROP_STATIC_HOSTNAME
]);
294 static int context_write_data_machine_info(Context
*c
) {
296 static const char * const name
[_PROP_MAX
] = {
297 [PROP_PRETTY_HOSTNAME
] = "PRETTY_HOSTNAME",
298 [PROP_ICON_NAME
] = "ICON_NAME",
299 [PROP_CHASSIS
] = "CHASSIS",
300 [PROP_DEPLOYMENT
] = "DEPLOYMENT",
301 [PROP_LOCATION
] = "LOCATION",
304 _cleanup_strv_free_
char **l
= NULL
;
309 r
= load_env_file(NULL
, "/etc/machine-info", &l
);
310 if (r
< 0 && r
!= -ENOENT
)
313 for (p
= PROP_PRETTY_HOSTNAME
; p
<= PROP_LOCATION
; p
++) {
314 _cleanup_free_
char *t
= NULL
;
319 if (isempty(c
->data
[p
])) {
320 strv_env_unset(l
, name
[p
]);
324 t
= strjoin(name
[p
], "=", c
->data
[p
]);
328 u
= strv_env_set(l
, t
);
332 strv_free_and_replace(l
, u
);
335 if (strv_isempty(l
)) {
336 if (unlink("/etc/machine-info") < 0)
337 return errno
== ENOENT
? 0 : -errno
;
342 return write_env_file_label("/etc/machine-info", l
);
345 static int property_get_icon_name(
348 const char *interface
,
349 const char *property
,
350 sd_bus_message
*reply
,
352 sd_bus_error
*error
) {
354 _cleanup_free_
char *n
= NULL
;
355 Context
*c
= userdata
;
358 if (isempty(c
->data
[PROP_ICON_NAME
]))
359 name
= n
= context_fallback_icon_name(c
);
361 name
= c
->data
[PROP_ICON_NAME
];
366 return sd_bus_message_append(reply
, "s", name
);
369 static int property_get_chassis(
372 const char *interface
,
373 const char *property
,
374 sd_bus_message
*reply
,
376 sd_bus_error
*error
) {
378 Context
*c
= userdata
;
381 if (isempty(c
->data
[PROP_CHASSIS
]))
382 name
= fallback_chassis();
384 name
= c
->data
[PROP_CHASSIS
];
386 return sd_bus_message_append(reply
, "s", name
);
389 static int property_get_uname_field(
392 const char *interface
,
393 const char *property
,
394 sd_bus_message
*reply
,
396 sd_bus_error
*error
) {
400 assert_se(uname(&u
) >= 0);
402 return sd_bus_message_append(reply
, "s", (char*) &u
+ PTR_TO_SIZE(userdata
));
405 static int method_set_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
406 Context
*c
= userdata
;
414 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
419 name
= c
->data
[PROP_STATIC_HOSTNAME
];
422 name
= FALLBACK_HOSTNAME
;
424 if (!hostname_is_valid(name
, false))
425 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", name
);
427 if (streq_ptr(name
, c
->data
[PROP_HOSTNAME
]))
428 return sd_bus_reply_method_return(m
, NULL
);
430 r
= bus_verify_polkit_async(
433 "org.freedesktop.hostname1.set-hostname",
442 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
444 r
= free_and_strdup(&c
->data
[PROP_HOSTNAME
], name
);
448 r
= context_update_kernel_hostname(c
);
450 log_error_errno(r
, "Failed to set hostname: %m");
451 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
454 log_info("Changed hostname to '%s'", strna(c
->data
[PROP_HOSTNAME
]));
456 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL
);
458 return sd_bus_reply_method_return(m
, NULL
);
461 static int method_set_static_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
462 Context
*c
= userdata
;
470 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
474 name
= empty_to_null(name
);
476 if (streq_ptr(name
, c
->data
[PROP_STATIC_HOSTNAME
]))
477 return sd_bus_reply_method_return(m
, NULL
);
479 if (!isempty(name
) && !hostname_is_valid(name
, false))
480 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid static hostname '%s'", name
);
482 r
= bus_verify_polkit_async(
485 "org.freedesktop.hostname1.set-static-hostname",
494 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
496 r
= free_and_strdup(&c
->data
[PROP_STATIC_HOSTNAME
], name
);
500 r
= context_update_kernel_hostname(c
);
502 log_error_errno(r
, "Failed to set hostname: %m");
503 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
506 r
= context_write_data_static_hostname(c
);
508 log_error_errno(r
, "Failed to write static hostname: %m");
509 return sd_bus_error_set_errnof(error
, r
, "Failed to set static hostname: %m");
512 log_info("Changed static hostname to '%s'", strna(c
->data
[PROP_STATIC_HOSTNAME
]));
514 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL
);
516 return sd_bus_reply_method_return(m
, NULL
);
519 static int set_machine_info(Context
*c
, sd_bus_message
*m
, int prop
, sd_bus_message_handler_t cb
, sd_bus_error
*error
) {
527 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
531 name
= empty_to_null(name
);
533 if (streq_ptr(name
, c
->data
[prop
]))
534 return sd_bus_reply_method_return(m
, NULL
);
536 if (!isempty(name
)) {
537 /* The icon name might ultimately be used as file
538 * name, so better be safe than sorry */
540 if (prop
== PROP_ICON_NAME
&& !filename_is_valid(name
))
541 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid icon name '%s'", name
);
542 if (prop
== PROP_PRETTY_HOSTNAME
&& string_has_cc(name
, NULL
))
543 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid pretty hostname '%s'", name
);
544 if (prop
== PROP_CHASSIS
&& !valid_chassis(name
))
545 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid chassis '%s'", name
);
546 if (prop
== PROP_DEPLOYMENT
&& !valid_deployment(name
))
547 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid deployment '%s'", name
);
548 if (prop
== PROP_LOCATION
&& string_has_cc(name
, NULL
))
549 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid location '%s'", name
);
552 /* Since the pretty hostname should always be changed at the
553 * same time as the static one, use the same policy action for
556 r
= bus_verify_polkit_async(
559 prop
== PROP_PRETTY_HOSTNAME
? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
568 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
570 r
= free_and_strdup(&c
->data
[prop
], name
);
574 r
= context_write_data_machine_info(c
);
576 log_error_errno(r
, "Failed to write machine info: %m");
577 return sd_bus_error_set_errnof(error
, r
, "Failed to write machine info: %m");
580 log_info("Changed %s to '%s'",
581 prop
== PROP_PRETTY_HOSTNAME
? "pretty hostname" :
582 prop
== PROP_DEPLOYMENT
? "deployment" :
583 prop
== PROP_LOCATION
? "location" :
584 prop
== PROP_CHASSIS
? "chassis" : "icon name", strna(c
->data
[prop
]));
586 (void) sd_bus_emit_properties_changed(
587 sd_bus_message_get_bus(m
),
588 "/org/freedesktop/hostname1",
589 "org.freedesktop.hostname1",
590 prop
== PROP_PRETTY_HOSTNAME
? "PrettyHostname" :
591 prop
== PROP_DEPLOYMENT
? "Deployment" :
592 prop
== PROP_LOCATION
? "Location" :
593 prop
== PROP_CHASSIS
? "Chassis" : "IconName" , NULL
);
595 return sd_bus_reply_method_return(m
, NULL
);
598 static int method_set_pretty_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
599 return set_machine_info(userdata
, m
, PROP_PRETTY_HOSTNAME
, method_set_pretty_hostname
, error
);
602 static int method_set_icon_name(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
603 return set_machine_info(userdata
, m
, PROP_ICON_NAME
, method_set_icon_name
, error
);
606 static int method_set_chassis(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
607 return set_machine_info(userdata
, m
, PROP_CHASSIS
, method_set_chassis
, error
);
610 static int method_set_deployment(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
611 return set_machine_info(userdata
, m
, PROP_DEPLOYMENT
, method_set_deployment
, error
);
614 static int method_set_location(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
615 return set_machine_info(userdata
, m
, PROP_LOCATION
, method_set_location
, error
);
618 static int method_get_product_uuid(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
619 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
620 Context
*c
= userdata
;
621 bool has_uuid
= false;
628 r
= id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID
, &uuid
);
630 r
= id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID
, &uuid
);
632 log_full_errno(r
== -ENOENT
? LOG_DEBUG
: LOG_WARNING
, r
,
633 "Failed to read product UUID, ignoring: %m");
634 else if (sd_id128_is_null(uuid
) || sd_id128_is_allf(uuid
))
635 log_debug("DMI product UUID " SD_ID128_FORMAT_STR
" is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(uuid
));
640 return sd_bus_error_set(error
, BUS_ERROR_NO_PRODUCT_UUID
,
641 "Failed to read product UUID from firmware.");
643 r
= sd_bus_message_read(m
, "b", &interactive
);
647 r
= bus_verify_polkit_async(
650 "org.freedesktop.hostname1.get-product-uuid",
659 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
661 r
= sd_bus_message_new_method_return(m
, &reply
);
665 r
= sd_bus_message_append_array(reply
, 'y', &uuid
, sizeof(uuid
));
669 return sd_bus_send(NULL
, reply
, NULL
);
672 static const sd_bus_vtable hostname_vtable
[] = {
673 SD_BUS_VTABLE_START(0),
674 SD_BUS_PROPERTY("Hostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
675 SD_BUS_PROPERTY("StaticHostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_STATIC_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
676 SD_BUS_PROPERTY("PrettyHostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_PRETTY_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
677 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
678 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
679 SD_BUS_PROPERTY("Deployment", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_DEPLOYMENT
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
680 SD_BUS_PROPERTY("Location", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_LOCATION
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
681 SD_BUS_PROPERTY("KernelName", "s", property_get_uname_field
, offsetof(struct utsname
, sysname
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("KernelRelease", "s", property_get_uname_field
, offsetof(struct utsname
, release
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("KernelVersion", "s", property_get_uname_field
, offsetof(struct utsname
, version
), SD_BUS_VTABLE_ABSOLUTE_OFFSET
|SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_PRETTY_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_CPE_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("HomeURL", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_HOME_URL
, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_METHOD_WITH_NAMES("SetHostname",
690 SD_BUS_PARAM(hostname
)
691 SD_BUS_PARAM(interactive
),
694 SD_BUS_VTABLE_UNPRIVILEGED
),
695 SD_BUS_METHOD_WITH_NAMES("SetStaticHostname",
697 SD_BUS_PARAM(hostname
)
698 SD_BUS_PARAM(interactive
),
700 method_set_static_hostname
,
701 SD_BUS_VTABLE_UNPRIVILEGED
),
702 SD_BUS_METHOD_WITH_NAMES("SetPrettyHostname",
704 SD_BUS_PARAM(hostname
)
705 SD_BUS_PARAM(interactive
),
707 method_set_pretty_hostname
,
708 SD_BUS_VTABLE_UNPRIVILEGED
),
709 SD_BUS_METHOD_WITH_NAMES("SetIconName",
712 SD_BUS_PARAM(interactive
),
714 method_set_icon_name
,
715 SD_BUS_VTABLE_UNPRIVILEGED
),
716 SD_BUS_METHOD_WITH_NAMES("SetChassis",
718 SD_BUS_PARAM(chassis
)
719 SD_BUS_PARAM(interactive
),
722 SD_BUS_VTABLE_UNPRIVILEGED
),
723 SD_BUS_METHOD_WITH_NAMES("SetDeployment",
725 SD_BUS_PARAM(deployment
)
726 SD_BUS_PARAM(interactive
),
728 method_set_deployment
,
729 SD_BUS_VTABLE_UNPRIVILEGED
),
730 SD_BUS_METHOD_WITH_NAMES("SetLocation",
732 SD_BUS_PARAM(location
)
733 SD_BUS_PARAM(interactive
),
736 SD_BUS_VTABLE_UNPRIVILEGED
),
737 SD_BUS_METHOD_WITH_NAMES("GetProductUUID",
739 SD_BUS_PARAM(interactive
),
742 method_get_product_uuid
,
743 SD_BUS_VTABLE_UNPRIVILEGED
),
748 static const BusObjectImplementation manager_object
= {
749 "/org/freedesktop/hostname1",
750 "org.freedesktop.hostname1",
751 .vtables
= BUS_VTABLES(hostname_vtable
),
754 static int connect_bus(Context
*c
, sd_event
*event
, sd_bus
**_bus
) {
755 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
762 r
= sd_bus_default_system(&bus
);
764 return log_error_errno(r
, "Failed to get system bus connection: %m");
766 r
= bus_add_implementation(bus
, &manager_object
, c
);
770 r
= bus_log_control_api_register(bus
);
774 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.hostname1", 0, NULL
, NULL
);
776 return log_error_errno(r
, "Failed to request name: %m");
778 r
= sd_bus_attach_event(bus
, event
, 0);
780 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
782 *_bus
= TAKE_PTR(bus
);
787 static int run(int argc
, char *argv
[]) {
788 _cleanup_(context_destroy
) Context context
= {};
789 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
790 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
795 r
= service_parse_argv("systemd-hostnamed.service",
796 "Manage the system hostname and related metadata.",
797 BUS_IMPLEMENTATIONS(&manager_object
,
798 &log_control_object
),
805 r
= mac_selinux_init();
809 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
811 r
= sd_event_default(&event
);
813 return log_error_errno(r
, "Failed to allocate event loop: %m");
815 (void) sd_event_set_watchdog(event
, true);
817 r
= sd_event_add_signal(event
, NULL
, SIGINT
, NULL
, NULL
);
819 return log_error_errno(r
, "Failed to install SIGINT handler: %m");
821 r
= sd_event_add_signal(event
, NULL
, SIGTERM
, NULL
, NULL
);
823 return log_error_errno(r
, "Failed to install SIGTERM handler: %m");
825 r
= connect_bus(&context
, event
, &bus
);
829 r
= context_read_data(&context
);
831 return log_error_errno(r
, "Failed to read hostname and machine information: %m");
833 r
= bus_event_loop_with_idle(event
, bus
, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC
, NULL
, NULL
);
835 return log_error_errno(r
, "Failed to run event loop: %m");
840 DEFINE_MAIN_FUNCTION(run
);