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-polkit.h"
13 #include "env-file-label.h"
16 #include "fileio-label.h"
18 #include "hostname-util.h"
19 #include "id128-util.h"
20 #include "main-func.h"
21 #include "missing_capability.h"
22 #include "nscd-flush.h"
23 #include "nulstr-util.h"
25 #include "parse-util.h"
26 #include "path-util.h"
27 #include "selinux-util.h"
28 #include "signal-util.h"
30 #include "user-util.h"
34 #define VALID_DEPLOYMENT_CHARS (DIGITS LETTERS "-.:")
53 typedef struct Context
{
54 char *data
[_PROP_MAX
];
55 Hashmap
*polkit_registry
;
60 static void context_reset(Context
*c
) {
65 for (p
= 0; p
< _PROP_MAX
; p
++)
66 c
->data
[p
] = mfree(c
->data
[p
]);
69 static void context_clear(Context
*c
) {
73 bus_verify_polkit_async_registry_free(c
->polkit_registry
);
76 static int context_read_data(Context
*c
) {
84 assert_se(uname(&u
) >= 0);
85 c
->data
[PROP_KERNEL_NAME
] = strdup(u
.sysname
);
86 c
->data
[PROP_KERNEL_RELEASE
] = strdup(u
.release
);
87 c
->data
[PROP_KERNEL_VERSION
] = strdup(u
.version
);
88 if (!c
->data
[PROP_KERNEL_NAME
] || !c
->data
[PROP_KERNEL_RELEASE
] ||
89 !c
->data
[PROP_KERNEL_VERSION
])
92 c
->data
[PROP_HOSTNAME
] = gethostname_malloc();
93 if (!c
->data
[PROP_HOSTNAME
])
96 r
= read_etc_hostname(NULL
, &c
->data
[PROP_STATIC_HOSTNAME
]);
97 if (r
< 0 && r
!= -ENOENT
)
100 r
= parse_env_file(NULL
, "/etc/machine-info",
101 "PRETTY_HOSTNAME", &c
->data
[PROP_PRETTY_HOSTNAME
],
102 "ICON_NAME", &c
->data
[PROP_ICON_NAME
],
103 "CHASSIS", &c
->data
[PROP_CHASSIS
],
104 "DEPLOYMENT", &c
->data
[PROP_DEPLOYMENT
],
105 "LOCATION", &c
->data
[PROP_LOCATION
]);
106 if (r
< 0 && r
!= -ENOENT
)
109 r
= parse_os_release(NULL
,
110 "PRETTY_NAME", &c
->data
[PROP_OS_PRETTY_NAME
],
111 "CPE_NAME", &c
->data
[PROP_OS_CPE_NAME
],
112 "HOME_URL", &c
->data
[PROP_HOME_URL
],
114 if (r
< 0 && r
!= -ENOENT
)
117 r
= id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID
, &c
->uuid
);
119 r
= id128_read("/sys/firmware/devicetree/base/vm,uuid", ID128_UUID
, &c
->uuid
);
121 log_full_errno(r
== -ENOENT
? LOG_DEBUG
: LOG_WARNING
, r
,
122 "Failed to read product UUID, ignoring: %m");
123 else if (sd_id128_is_null(c
->uuid
) || sd_id128_is_allf(c
->uuid
))
124 log_debug("DMI product UUID " SD_ID128_FORMAT_STR
" is all 0x00 or all 0xFF, ignoring.", SD_ID128_FORMAT_VAL(c
->uuid
));
131 static bool valid_chassis(const char *chassis
) {
134 return nulstr_contains(
148 static bool valid_deployment(const char *deployment
) {
151 return in_charset(deployment
, VALID_DEPLOYMENT_CHARS
);
154 static const char* fallback_chassis(void) {
159 v
= detect_virtualization();
160 if (VIRTUALIZATION_IS_VM(v
))
162 if (VIRTUALIZATION_IS_CONTAINER(v
))
165 r
= read_one_line_file("/sys/class/dmi/id/chassis_type", &type
);
169 r
= safe_atou(type
, &t
);
174 /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
175 additional guesswork on top of that.
177 See the SMBIOS Specification 3.0 section 7.4.1 for details about the values listed here:
179 https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.0.0.pdf
184 case 0x3: /* Desktop */
185 case 0x4: /* Low Profile Desktop */
186 case 0x6: /* Mini Tower */
187 case 0x7: /* Tower */
190 case 0x8: /* Portable */
191 case 0x9: /* Laptop */
192 case 0xA: /* Notebook */
193 case 0xE: /* Sub Notebook */
196 case 0xB: /* Hand Held */
199 case 0x11: /* Main Server Chassis */
200 case 0x1C: /* Blade */
201 case 0x1D: /* Blade Enclosure */
204 case 0x1E: /* Tablet */
207 case 0x1F: /* Convertible */
208 case 0x20: /* Detachable */
209 return "convertible";
213 r
= read_one_line_file("/sys/firmware/acpi/pm_profile", &type
);
217 r
= safe_atou(type
, &t
);
222 /* We only list the really obvious cases here as the ACPI data is not really super reliable.
224 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
226 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
231 case 1: /* Desktop */
232 case 3: /* Workstation */
233 case 6: /* Appliance PC */
239 case 4: /* Enterprise Server */
240 case 5: /* SOHO Server */
241 case 7: /* Performance Server */
251 static char* context_fallback_icon_name(Context
*c
) {
256 if (!isempty(c
->data
[PROP_CHASSIS
]))
257 return strjoin("computer-", c
->data
[PROP_CHASSIS
]);
259 chassis
= fallback_chassis();
261 return strjoin("computer-", chassis
);
263 return strdup("computer");
266 static bool hostname_is_useful(const char *hn
) {
267 return !isempty(hn
) && !is_localhost(hn
);
270 static int context_update_kernel_hostname(Context
*c
) {
271 const char *static_hn
;
276 static_hn
= c
->data
[PROP_STATIC_HOSTNAME
];
278 /* /etc/hostname with something other than "localhost"
279 * has the highest preference ... */
280 if (hostname_is_useful(static_hn
))
283 /* ... the transient hostname, (ie: DHCP) comes next ... */
284 else if (!isempty(c
->data
[PROP_HOSTNAME
]))
285 hn
= c
->data
[PROP_HOSTNAME
];
287 /* ... fallback to static "localhost.*" ignored above ... */
288 else if (!isempty(static_hn
))
291 /* ... and the ultimate fallback */
293 hn
= FALLBACK_HOSTNAME
;
295 if (sethostname_idempotent(hn
) < 0)
298 (void) nscd_flush_cache(STRV_MAKE("hosts"));
303 static int context_write_data_static_hostname(Context
*c
) {
307 if (isempty(c
->data
[PROP_STATIC_HOSTNAME
])) {
309 if (unlink("/etc/hostname") < 0)
310 return errno
== ENOENT
? 0 : -errno
;
314 return write_string_file_atomic_label("/etc/hostname", c
->data
[PROP_STATIC_HOSTNAME
]);
317 static int context_write_data_machine_info(Context
*c
) {
319 static const char * const name
[_PROP_MAX
] = {
320 [PROP_PRETTY_HOSTNAME
] = "PRETTY_HOSTNAME",
321 [PROP_ICON_NAME
] = "ICON_NAME",
322 [PROP_CHASSIS
] = "CHASSIS",
323 [PROP_DEPLOYMENT
] = "DEPLOYMENT",
324 [PROP_LOCATION
] = "LOCATION",
327 _cleanup_strv_free_
char **l
= NULL
;
332 r
= load_env_file(NULL
, "/etc/machine-info", &l
);
333 if (r
< 0 && r
!= -ENOENT
)
336 for (p
= PROP_PRETTY_HOSTNAME
; p
<= PROP_LOCATION
; p
++) {
337 _cleanup_free_
char *t
= NULL
;
342 if (isempty(c
->data
[p
])) {
343 strv_env_unset(l
, name
[p
]);
347 t
= strjoin(name
[p
], "=", c
->data
[p
]);
351 u
= strv_env_set(l
, t
);
355 strv_free_and_replace(l
, u
);
358 if (strv_isempty(l
)) {
359 if (unlink("/etc/machine-info") < 0)
360 return errno
== ENOENT
? 0 : -errno
;
365 return write_env_file_label("/etc/machine-info", l
);
368 static int property_get_icon_name(
371 const char *interface
,
372 const char *property
,
373 sd_bus_message
*reply
,
375 sd_bus_error
*error
) {
377 _cleanup_free_
char *n
= NULL
;
378 Context
*c
= userdata
;
381 if (isempty(c
->data
[PROP_ICON_NAME
]))
382 name
= n
= context_fallback_icon_name(c
);
384 name
= c
->data
[PROP_ICON_NAME
];
389 return sd_bus_message_append(reply
, "s", name
);
392 static int property_get_chassis(
395 const char *interface
,
396 const char *property
,
397 sd_bus_message
*reply
,
399 sd_bus_error
*error
) {
401 Context
*c
= userdata
;
404 if (isempty(c
->data
[PROP_CHASSIS
]))
405 name
= fallback_chassis();
407 name
= c
->data
[PROP_CHASSIS
];
409 return sd_bus_message_append(reply
, "s", name
);
412 static int method_set_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
413 Context
*c
= userdata
;
421 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
426 name
= c
->data
[PROP_STATIC_HOSTNAME
];
429 name
= FALLBACK_HOSTNAME
;
431 if (!hostname_is_valid(name
, false))
432 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid hostname '%s'", name
);
434 if (streq_ptr(name
, c
->data
[PROP_HOSTNAME
]))
435 return sd_bus_reply_method_return(m
, NULL
);
437 r
= bus_verify_polkit_async(
440 "org.freedesktop.hostname1.set-hostname",
449 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
451 r
= free_and_strdup(&c
->data
[PROP_HOSTNAME
], name
);
455 r
= context_update_kernel_hostname(c
);
457 log_error_errno(r
, "Failed to set hostname: %m");
458 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
461 log_info("Changed hostname to '%s'", strna(c
->data
[PROP_HOSTNAME
]));
463 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL
);
465 return sd_bus_reply_method_return(m
, NULL
);
468 static int method_set_static_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
469 Context
*c
= userdata
;
477 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
481 name
= empty_to_null(name
);
483 if (streq_ptr(name
, c
->data
[PROP_STATIC_HOSTNAME
]))
484 return sd_bus_reply_method_return(m
, NULL
);
486 if (!isempty(name
) && !hostname_is_valid(name
, false))
487 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid static hostname '%s'", name
);
489 r
= bus_verify_polkit_async(
492 "org.freedesktop.hostname1.set-static-hostname",
501 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
503 r
= free_and_strdup(&c
->data
[PROP_STATIC_HOSTNAME
], name
);
507 r
= context_update_kernel_hostname(c
);
509 log_error_errno(r
, "Failed to set hostname: %m");
510 return sd_bus_error_set_errnof(error
, r
, "Failed to set hostname: %m");
513 r
= context_write_data_static_hostname(c
);
515 log_error_errno(r
, "Failed to write static hostname: %m");
516 return sd_bus_error_set_errnof(error
, r
, "Failed to set static hostname: %m");
519 log_info("Changed static hostname to '%s'", strna(c
->data
[PROP_STATIC_HOSTNAME
]));
521 (void) sd_bus_emit_properties_changed(sd_bus_message_get_bus(m
), "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL
);
523 return sd_bus_reply_method_return(m
, NULL
);
526 static int set_machine_info(Context
*c
, sd_bus_message
*m
, int prop
, sd_bus_message_handler_t cb
, sd_bus_error
*error
) {
534 r
= sd_bus_message_read(m
, "sb", &name
, &interactive
);
538 name
= empty_to_null(name
);
540 if (streq_ptr(name
, c
->data
[prop
]))
541 return sd_bus_reply_method_return(m
, NULL
);
543 if (!isempty(name
)) {
544 /* The icon name might ultimately be used as file
545 * name, so better be safe than sorry */
547 if (prop
== PROP_ICON_NAME
&& !filename_is_valid(name
))
548 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid icon name '%s'", name
);
549 if (prop
== PROP_PRETTY_HOSTNAME
&& string_has_cc(name
, NULL
))
550 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid pretty hostname '%s'", name
);
551 if (prop
== PROP_CHASSIS
&& !valid_chassis(name
))
552 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid chassis '%s'", name
);
553 if (prop
== PROP_DEPLOYMENT
&& !valid_deployment(name
))
554 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid deployment '%s'", name
);
555 if (prop
== PROP_LOCATION
&& string_has_cc(name
, NULL
))
556 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid location '%s'", name
);
559 /* Since the pretty hostname should always be changed at the
560 * same time as the static one, use the same policy action for
563 r
= bus_verify_polkit_async(
566 prop
== PROP_PRETTY_HOSTNAME
? "org.freedesktop.hostname1.set-static-hostname" : "org.freedesktop.hostname1.set-machine-info",
575 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
577 r
= free_and_strdup(&c
->data
[prop
], name
);
581 r
= context_write_data_machine_info(c
);
583 log_error_errno(r
, "Failed to write machine info: %m");
584 return sd_bus_error_set_errnof(error
, r
, "Failed to write machine info: %m");
587 log_info("Changed %s to '%s'",
588 prop
== PROP_PRETTY_HOSTNAME
? "pretty hostname" :
589 prop
== PROP_DEPLOYMENT
? "deployment" :
590 prop
== PROP_LOCATION
? "location" :
591 prop
== PROP_CHASSIS
? "chassis" : "icon name", strna(c
->data
[prop
]));
593 (void) sd_bus_emit_properties_changed(
594 sd_bus_message_get_bus(m
),
595 "/org/freedesktop/hostname1",
596 "org.freedesktop.hostname1",
597 prop
== PROP_PRETTY_HOSTNAME
? "PrettyHostname" :
598 prop
== PROP_DEPLOYMENT
? "Deployment" :
599 prop
== PROP_LOCATION
? "Location" :
600 prop
== PROP_CHASSIS
? "Chassis" : "IconName" , NULL
);
602 return sd_bus_reply_method_return(m
, NULL
);
605 static int method_set_pretty_hostname(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
606 return set_machine_info(userdata
, m
, PROP_PRETTY_HOSTNAME
, method_set_pretty_hostname
, error
);
609 static int method_set_icon_name(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
610 return set_machine_info(userdata
, m
, PROP_ICON_NAME
, method_set_icon_name
, error
);
613 static int method_set_chassis(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
614 return set_machine_info(userdata
, m
, PROP_CHASSIS
, method_set_chassis
, error
);
617 static int method_set_deployment(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
618 return set_machine_info(userdata
, m
, PROP_DEPLOYMENT
, method_set_deployment
, error
);
621 static int method_set_location(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
622 return set_machine_info(userdata
, m
, PROP_LOCATION
, method_set_location
, error
);
625 static int method_get_product_uuid(sd_bus_message
*m
, void *userdata
, sd_bus_error
*error
) {
626 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
627 Context
*c
= userdata
;
634 return sd_bus_error_set(error
, BUS_ERROR_NO_PRODUCT_UUID
, "Failed to read product UUID from /sys/class/dmi/id/product_uuid");
636 r
= sd_bus_message_read(m
, "b", &interactive
);
640 r
= bus_verify_polkit_async(
643 "org.freedesktop.hostname1.get-product-uuid",
652 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
654 r
= sd_bus_message_new_method_return(m
, &reply
);
658 r
= sd_bus_message_append_array(reply
, 'y', &c
->uuid
, sizeof(c
->uuid
));
662 return sd_bus_send(NULL
, reply
, NULL
);
665 static const sd_bus_vtable hostname_vtable
[] = {
666 SD_BUS_VTABLE_START(0),
667 SD_BUS_PROPERTY("Hostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
668 SD_BUS_PROPERTY("StaticHostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_STATIC_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
669 SD_BUS_PROPERTY("PrettyHostname", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_PRETTY_HOSTNAME
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
670 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
671 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis
, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
672 SD_BUS_PROPERTY("Deployment", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_DEPLOYMENT
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
673 SD_BUS_PROPERTY("Location", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_LOCATION
, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
674 SD_BUS_PROPERTY("KernelName", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_KERNEL_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("KernelRelease", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_KERNEL_RELEASE
, SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("KernelVersion", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_KERNEL_VERSION
, SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("OperatingSystemPrettyName", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_PRETTY_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("OperatingSystemCPEName", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_OS_CPE_NAME
, SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("HomeURL", "s", NULL
, offsetof(Context
, data
) + sizeof(char*) * PROP_HOME_URL
, SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_METHOD_WITH_NAMES("SetHostname",
683 SD_BUS_PARAM(hostname
)
684 SD_BUS_PARAM(interactive
),
687 SD_BUS_VTABLE_UNPRIVILEGED
),
688 SD_BUS_METHOD_WITH_NAMES("SetStaticHostname",
690 SD_BUS_PARAM(hostname
)
691 SD_BUS_PARAM(interactive
),
693 method_set_static_hostname
,
694 SD_BUS_VTABLE_UNPRIVILEGED
),
695 SD_BUS_METHOD_WITH_NAMES("SetPrettyHostname",
697 SD_BUS_PARAM(hostname
)
698 SD_BUS_PARAM(interactive
),
700 method_set_pretty_hostname
,
701 SD_BUS_VTABLE_UNPRIVILEGED
),
702 SD_BUS_METHOD_WITH_NAMES("SetIconName",
705 SD_BUS_PARAM(interactive
),
707 method_set_icon_name
,
708 SD_BUS_VTABLE_UNPRIVILEGED
),
709 SD_BUS_METHOD_WITH_NAMES("SetChassis",
711 SD_BUS_PARAM(chassis
)
712 SD_BUS_PARAM(interactive
),
715 SD_BUS_VTABLE_UNPRIVILEGED
),
716 SD_BUS_METHOD_WITH_NAMES("SetDeployment",
718 SD_BUS_PARAM(deployment
)
719 SD_BUS_PARAM(interactive
),
721 method_set_deployment
,
722 SD_BUS_VTABLE_UNPRIVILEGED
),
723 SD_BUS_METHOD_WITH_NAMES("SetLocation",
725 SD_BUS_PARAM(location
)
726 SD_BUS_PARAM(interactive
),
729 SD_BUS_VTABLE_UNPRIVILEGED
),
730 SD_BUS_METHOD_WITH_NAMES("GetProductUUID",
732 SD_BUS_PARAM(interactive
),
735 method_get_product_uuid
,
736 SD_BUS_VTABLE_UNPRIVILEGED
),
741 static int connect_bus(Context
*c
, sd_event
*event
, sd_bus
**_bus
) {
742 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
749 r
= sd_bus_default_system(&bus
);
751 return log_error_errno(r
, "Failed to get system bus connection: %m");
753 r
= sd_bus_add_object_vtable(bus
, NULL
, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable
, c
);
755 return log_error_errno(r
, "Failed to register object: %m");
757 r
= sd_bus_request_name_async(bus
, NULL
, "org.freedesktop.hostname1", 0, NULL
, NULL
);
759 return log_error_errno(r
, "Failed to request name: %m");
761 r
= sd_bus_attach_event(bus
, event
, 0);
763 return log_error_errno(r
, "Failed to attach bus to event loop: %m");
765 *_bus
= TAKE_PTR(bus
);
770 static int run(int argc
, char *argv
[]) {
771 _cleanup_(context_clear
) Context context
= {};
772 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
773 _cleanup_(sd_bus_flush_close_unrefp
) sd_bus
*bus
= NULL
;
782 log_error("This program takes no arguments.");
786 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
788 r
= sd_event_default(&event
);
790 return log_error_errno(r
, "Failed to allocate event loop: %m");
792 (void) sd_event_set_watchdog(event
, true);
794 r
= sd_event_add_signal(event
, NULL
, SIGINT
, NULL
, NULL
);
796 return log_error_errno(r
, "Failed to install SIGINT handler: %m");
798 r
= sd_event_add_signal(event
, NULL
, SIGTERM
, NULL
, NULL
);
800 return log_error_errno(r
, "Failed to install SIGTERM handler: %m");
802 r
= connect_bus(&context
, event
, &bus
);
806 r
= context_read_data(&context
);
808 return log_error_errno(r
, "Failed to read hostname and machine information: %m");
810 r
= bus_event_loop_with_idle(event
, bus
, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC
, NULL
, NULL
);
812 return log_error_errno(r
, "Failed to run event loop: %m");
817 DEFINE_MAIN_FUNCTION(run
);