]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/hostname/hostnamed.c
bus: reenable id change subscriptions
[thirdparty/systemd.git] / src / hostname / hostnamed.c
CommitLineData
7640a5de
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
41550d40 6 Copyright 2011 Lennart Poettering
7640a5de
LP
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
7640a5de
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
7640a5de 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
7640a5de
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
7640a5de
LP
22#include <errno.h>
23#include <string.h>
24#include <unistd.h>
c2a14cf0 25#include <dlfcn.h>
7640a5de
LP
26
27#include "util.h"
28#include "strv.h"
ad740100 29#include "def.h"
b52aae1d 30#include "virt.h"
4d1a6904 31#include "env-util.h"
a5c32cff
HH
32#include "fileio-label.h"
33#include "label.h"
66a4c743
LP
34#include "bus-util.h"
35#include "event-util.h"
91f9dcaf 36
7640a5de
LP
37enum {
38 PROP_HOSTNAME,
39 PROP_STATIC_HOSTNAME,
40 PROP_PRETTY_HOSTNAME,
41 PROP_ICON_NAME,
7871c8e9 42 PROP_CHASSIS,
7640a5de
LP
43 _PROP_MAX
44};
45
66a4c743
LP
46typedef struct Context {
47 char *data[_PROP_MAX];
48 Hashmap *polkit_registry;
49} Context;
ad740100 50
66a4c743 51static void context_reset(Context *c) {
7640a5de
LP
52 int p;
53
66a4c743
LP
54 assert(c);
55
7640a5de 56 for (p = 0; p < _PROP_MAX; p++) {
66a4c743
LP
57 free(c->data[p]);
58 c->data[p] = NULL;
7640a5de
LP
59 }
60}
61
66a4c743
LP
62static void context_free(Context *c, sd_bus *bus) {
63 assert(c);
64
65 context_reset(c);
66 bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
67}
68
69static int context_read_data(Context *c) {
7640a5de
LP
70 int r;
71
66a4c743
LP
72 assert(c);
73
74 context_reset(c);
7640a5de 75
66a4c743
LP
76 c->data[PROP_HOSTNAME] = gethostname_malloc();
77 if (!c->data[PROP_HOSTNAME])
7640a5de
LP
78 return -ENOMEM;
79
66a4c743 80 r = read_one_line_file("/etc/hostname", &c->data[PROP_STATIC_HOSTNAME]);
7640a5de
LP
81 if (r < 0 && r != -ENOENT)
82 return r;
83
84 r = parse_env_file("/etc/machine-info", NEWLINE,
66a4c743
LP
85 "PRETTY_HOSTNAME", &c->data[PROP_PRETTY_HOSTNAME],
86 "ICON_NAME", &c->data[PROP_ICON_NAME],
87 "CHASSIS", &c->data[PROP_CHASSIS],
7640a5de
LP
88 NULL);
89 if (r < 0 && r != -ENOENT)
90 return r;
91
92 return 0;
93}
94
c2a14cf0 95static bool check_nss(void) {
c2a14cf0
LP
96 void *dl;
97
7871c8e9
LP
98 dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY);
99 if (dl) {
c2a14cf0
LP
100 dlclose(dl);
101 return true;
102 }
103
104 return false;
105}
106
7871c8e9 107static bool valid_chassis(const char *chassis) {
7640a5de 108
7871c8e9
LP
109 assert(chassis);
110
111 return nulstr_contains(
112 "vm\0"
113 "container\0"
114 "desktop\0"
115 "laptop\0"
116 "server\0"
117 "tablet\0"
118 "handset\0",
119 chassis);
120}
121
122static const char* fallback_chassis(void) {
7640a5de
LP
123 int r;
124 char *type;
125 unsigned t;
7871c8e9
LP
126 Virtualization v;
127
128 v = detect_virtualization(NULL);
129
130 if (v == VIRTUALIZATION_VM)
131 return "vm";
132 if (v == VIRTUALIZATION_CONTAINER)
133 return "container";
134
135 r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
136 if (r < 0)
137 goto try_dmi;
138
139 r = safe_atou(type, &t);
140 free(type);
141 if (r < 0)
142 goto try_dmi;
143
144 /* We only list the really obvious cases here as the ACPI data
145 * is not really super reliable.
146 *
147 * See the ACPI 5.0 Spec Section 5.2.9.1 for details:
148 *
149 * http://www.acpi.info/DOWNLOADS/ACPIspec50.pdf
150 */
151
152 switch(t) {
153
154 case 1:
155 case 3:
156 case 6:
157 return "desktop";
158
159 case 2:
160 return "laptop";
7640a5de 161
7871c8e9
LP
162 case 4:
163 case 5:
164 case 7:
165 return "server";
7640a5de 166
7871c8e9
LP
167 case 8:
168 return "tablet";
169 }
170
171try_dmi:
7640a5de
LP
172 r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
173 if (r < 0)
174 return NULL;
175
176 r = safe_atou(type, &t);
177 free(type);
7640a5de
LP
178 if (r < 0)
179 return NULL;
180
181 /* We only list the really obvious cases here. The DMI data is
182 unreliable enough, so let's not do any additional guesswork
41550d40
LP
183 on top of that.
184
185 See the SMBIOS Specification 2.7.1 section 7.4.1 for
186 details about the values listed here:
187
188 http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
189 */
7640a5de
LP
190
191 switch (t) {
192
193 case 0x3:
194 case 0x4:
195 case 0x6:
196 case 0x7:
7871c8e9 197 return "desktop";
7640a5de 198
7871c8e9 199 case 0x8:
7640a5de
LP
200 case 0x9:
201 case 0xA:
202 case 0xE:
7871c8e9
LP
203 return "laptop";
204
205 case 0xB:
206 return "handset";
7640a5de
LP
207
208 case 0x11:
41550d40 209 case 0x1C:
7871c8e9 210 return "server";
7640a5de
LP
211 }
212
7640a5de
LP
213 return NULL;
214}
215
66a4c743 216static char* context_fallback_icon_name(Context *c) {
7871c8e9
LP
217 const char *chassis;
218
66a4c743
LP
219 assert(c);
220
221 if (!isempty(c->data[PROP_CHASSIS]))
222 return strappend("computer-", c->data[PROP_CHASSIS]);
7871c8e9
LP
223
224 chassis = fallback_chassis();
225 if (chassis)
226 return strappend("computer-", chassis);
227
228 return strdup("computer");
229}
230
66a4c743 231static int context_write_data_hostname(Context *c) {
7640a5de
LP
232 const char *hn;
233
66a4c743
LP
234 assert(c);
235
236 if (isempty(c->data[PROP_HOSTNAME]))
7640a5de
LP
237 hn = "localhost";
238 else
66a4c743 239 hn = c->data[PROP_HOSTNAME];
7640a5de
LP
240
241 if (sethostname(hn, strlen(hn)) < 0)
242 return -errno;
243
244 return 0;
245}
246
66a4c743 247static int context_write_data_static_hostname(Context *c) {
7640a5de 248
66a4c743
LP
249 assert(c);
250
251 if (isempty(c->data[PROP_STATIC_HOSTNAME])) {
7640a5de
LP
252
253 if (unlink("/etc/hostname") < 0)
254 return errno == ENOENT ? 0 : -errno;
255
256 return 0;
257 }
66a4c743 258 return write_string_file_atomic_label("/etc/hostname", c->data[PROP_STATIC_HOSTNAME]);
7640a5de
LP
259}
260
66a4c743 261static int context_write_data_other(Context *c) {
4f34ed54 262
7640a5de
LP
263 static const char * const name[_PROP_MAX] = {
264 [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
7871c8e9
LP
265 [PROP_ICON_NAME] = "ICON_NAME",
266 [PROP_CHASSIS] = "CHASSIS"
7640a5de
LP
267 };
268
0ccad099 269 _cleanup_strv_free_ char **l = NULL;
7640a5de
LP
270 int r, p;
271
66a4c743
LP
272 assert(c);
273
f73141d7 274 r = load_env_file("/etc/machine-info", NULL, &l);
7640a5de
LP
275 if (r < 0 && r != -ENOENT)
276 return r;
277
278 for (p = 2; p < _PROP_MAX; p++) {
279 char *t, **u;
280
281 assert(name[p]);
282
66a4c743 283 if (isempty(c->data[p])) {
f8440af5 284 strv_env_unset(l, name[p]);
7640a5de
LP
285 continue;
286 }
287
0ccad099 288 if (asprintf(&t, "%s=%s", name[p], strempty(c->data[p])) < 0)
7640a5de 289 return -ENOMEM;
7640a5de
LP
290
291 u = strv_env_set(l, t);
292 free(t);
7640a5de
LP
293
294 if (!u)
295 return -ENOMEM;
0ccad099
LP
296
297 strv_free(l);
7640a5de
LP
298 l = u;
299 }
300
301 if (strv_isempty(l)) {
302
303 if (unlink("/etc/machine-info") < 0)
304 return errno == ENOENT ? 0 : -errno;
305
306 return 0;
307 }
308
0ccad099 309 return write_env_file_label("/etc/machine-info", l);
7640a5de
LP
310}
311
66a4c743
LP
312static int property_get_icon_name(
313 sd_bus *bus,
314 const char *path,
315 const char *interface,
316 const char *property,
317 sd_bus_message *reply,
ebcf1f97
LP
318 void *userdata,
319 sd_bus_error *error) {
7640a5de 320
66a4c743
LP
321 _cleanup_free_ char *n = NULL;
322 Context *c = userdata;
323 const char *name;
7640a5de 324
66a4c743
LP
325 if (isempty(c->data[PROP_ICON_NAME]))
326 name = n = context_fallback_icon_name(c);
7640a5de 327 else
66a4c743
LP
328 name = c->data[PROP_ICON_NAME];
329
330 if (!name)
331 return -ENOMEM;
7640a5de 332
ebcf1f97 333 return sd_bus_message_append(reply, "s", name);
7640a5de
LP
334}
335
66a4c743
LP
336static int property_get_chassis(
337 sd_bus *bus,
338 const char *path,
339 const char *interface,
340 const char *property,
341 sd_bus_message *reply,
ebcf1f97
LP
342 void *userdata,
343 sd_bus_error *error) {
7871c8e9 344
66a4c743
LP
345 Context *c = userdata;
346 const char *name;
7871c8e9 347
66a4c743 348 if (isempty(c->data[PROP_CHASSIS]))
7871c8e9
LP
349 name = fallback_chassis();
350 else
66a4c743 351 name = c->data[PROP_CHASSIS];
7871c8e9 352
ebcf1f97 353 return sd_bus_message_append(reply, "s", name);
7871c8e9
LP
354}
355
ebcf1f97 356static int method_set_hostname(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
66a4c743
LP
357 Context *c = userdata;
358 const char *name;
102d8f81 359 int interactive;
66a4c743
LP
360 char *h;
361 int r;
d200735e 362
66a4c743
LP
363 r = sd_bus_message_read(m, "sb", &name, &interactive);
364 if (r < 0)
ebcf1f97 365 return r;
d200735e 366
66a4c743
LP
367 if (isempty(name))
368 name = c->data[PROP_STATIC_HOSTNAME];
7640a5de 369
66a4c743
LP
370 if (isempty(name))
371 name = "localhost";
7640a5de 372
66a4c743 373 if (!hostname_is_valid(name))
ebcf1f97 374 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid hostname '%s'", name);
7640a5de 375
66a4c743 376 if (streq_ptr(name, c->data[PROP_HOSTNAME]))
df2d202e 377 return sd_bus_reply_method_return(m, NULL);
7640a5de 378
ebcf1f97 379 r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-hostname", interactive, error, method_set_hostname, c);
66a4c743 380 if (r < 0)
ebcf1f97 381 return r;
66a4c743
LP
382 if (r == 0)
383 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
7640a5de 384
66a4c743
LP
385 h = strdup(name);
386 if (!h)
ebcf1f97 387 return -ENOMEM;
7640a5de 388
66a4c743
LP
389 free(c->data[PROP_HOSTNAME]);
390 c->data[PROP_HOSTNAME] = h;
7640a5de 391
66a4c743
LP
392 r = context_write_data_hostname(c);
393 if (r < 0) {
394 log_error("Failed to set host name: %s", strerror(-r));
ebcf1f97 395 return sd_bus_error_set_errnof(error, r, "Failed to set hostname: %s", strerror(-r));
66a4c743 396 }
7640a5de 397
66a4c743 398 log_info("Changed host name to '%s'", strna(c->data[PROP_HOSTNAME]));
7640a5de 399
66a4c743 400 sd_bus_emit_properties_changed(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "Hostname", NULL);
7640a5de 401
df2d202e 402 return sd_bus_reply_method_return(m, NULL);
66a4c743 403}
7640a5de 404
ebcf1f97 405static int method_set_static_hostname(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
66a4c743
LP
406 Context *c = userdata;
407 const char *name;
102d8f81 408 int interactive;
66a4c743 409 int r;
7640a5de 410
66a4c743
LP
411 r = sd_bus_message_read(m, "sb", &name, &interactive);
412 if (r < 0)
ebcf1f97 413 return r;
7640a5de 414
66a4c743
LP
415 if (isempty(name))
416 name = NULL;
7640a5de 417
66a4c743 418 if (streq_ptr(name, c->data[PROP_STATIC_HOSTNAME]))
df2d202e 419 return sd_bus_reply_method_return(m, NULL);
7640a5de 420
ebcf1f97 421 r = bus_verify_polkit_async(bus, &c->polkit_registry, m, "org.freedesktop.hostname1.set-static-hostname", interactive, error, method_set_static_hostname, c);
66a4c743 422 if (r < 0)
ebcf1f97 423 return r;
66a4c743
LP
424 if (r == 0)
425 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
7640a5de 426
66a4c743
LP
427 if (isempty(name)) {
428 free(c->data[PROP_STATIC_HOSTNAME]);
429 c->data[PROP_STATIC_HOSTNAME] = NULL;
430 } else {
431 char *h;
7640a5de 432
66a4c743 433 if (!hostname_is_valid(name))
ebcf1f97 434 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid static hostname '%s'", name);
7640a5de 435
66a4c743
LP
436 h = strdup(name);
437 if (!h)
ebcf1f97 438 return -ENOMEM;
7640a5de 439
66a4c743
LP
440 free(c->data[PROP_STATIC_HOSTNAME]);
441 c->data[PROP_STATIC_HOSTNAME] = h;
442 }
7640a5de 443
66a4c743
LP
444 r = context_write_data_static_hostname(c);
445 if (r < 0) {
446 log_error("Failed to write static host name: %s", strerror(-r));
ebcf1f97 447 return sd_bus_error_set_errnof(error, r, "Failed to set static hostname: %s", strerror(-r));
66a4c743 448 }
7640a5de 449
66a4c743 450 log_info("Changed static host name to '%s'", strna(c->data[PROP_STATIC_HOSTNAME]));
7640a5de 451
66a4c743 452 sd_bus_emit_properties_changed(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "StaticHostname", NULL);
7640a5de 453
df2d202e 454 return sd_bus_reply_method_return(m, NULL);
66a4c743 455}
7640a5de 456
ebcf1f97 457static int set_machine_info(Context *c, sd_bus *bus, sd_bus_message *m, int prop, sd_bus_message_handler_t cb, sd_bus_error *error) {
102d8f81 458 int interactive;
66a4c743
LP
459 const char *name;
460 int r;
461
462 assert(c);
463 assert(bus);
464 assert(m);
465
466 r = sd_bus_message_read(m, "sb", &name, &interactive);
467 if (r < 0)
ebcf1f97 468 return r;
66a4c743
LP
469
470 if (isempty(name))
471 name = NULL;
472
473 if (streq_ptr(name, c->data[prop]))
df2d202e 474 return sd_bus_reply_method_return(m, NULL);
7640a5de 475
66a4c743
LP
476 /* Since the pretty hostname should always be changed at the
477 * same time as the static one, use the same policy action for
478 * both... */
479
480 r = bus_verify_polkit_async(bus, &c->polkit_registry, m, prop == PROP_PRETTY_HOSTNAME ?
481 "org.freedesktop.hostname1.set-static-hostname" :
ebcf1f97 482 "org.freedesktop.hostname1.set-machine-info", interactive, error, cb, c);
66a4c743 483 if (r < 0)
ebcf1f97 484 return r;
66a4c743
LP
485 if (r == 0)
486 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
487
488 if (isempty(name)) {
489 free(c->data[prop]);
490 c->data[prop] = NULL;
491 } else {
492 char *h;
493
494 /* The icon name might ultimately be used as file
495 * name, so better be safe than sorry */
496
497 if (prop == PROP_ICON_NAME && !filename_is_safe(name))
ebcf1f97 498 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid icon name '%s'", name);
66a4c743
LP
499 if (prop == PROP_PRETTY_HOSTNAME &&
500 (string_has_cc(name) || chars_intersect(name, "\t")))
ebcf1f97 501 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid pretty host name '%s'", name);
66a4c743 502 if (prop == PROP_CHASSIS && !valid_chassis(name))
ebcf1f97 503 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid chassis '%s'", name);
66a4c743
LP
504
505 h = strdup(name);
506 if (!h)
ebcf1f97 507 return -ENOMEM;
66a4c743
LP
508
509 free(c->data[prop]);
510 c->data[prop] = h;
7640a5de
LP
511 }
512
66a4c743
LP
513 r = context_write_data_other(c);
514 if (r < 0) {
515 log_error("Failed to write machine info: %s", strerror(-r));
ebcf1f97 516 return sd_bus_error_set_errnof(error, r, "Failed to write machine info: %s", strerror(-r));
66a4c743 517 }
7640a5de 518
66a4c743
LP
519 log_info("Changed %s to '%s'",
520 prop == PROP_PRETTY_HOSTNAME ? "pretty host name" :
521 prop == PROP_CHASSIS ? "chassis" : "icon name", strna(c->data[prop]));
7640a5de 522
66a4c743
LP
523 sd_bus_emit_properties_changed(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1",
524 prop == PROP_PRETTY_HOSTNAME ? "PrettyHostname" :
525 prop == PROP_CHASSIS ? "Chassis" : "IconName", NULL);
7640a5de 526
df2d202e 527 return sd_bus_reply_method_return(m, NULL);
66a4c743 528}
7640a5de 529
ebcf1f97
LP
530static int method_set_pretty_hostname(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
531 return set_machine_info(userdata, bus, m, PROP_PRETTY_HOSTNAME, method_set_pretty_hostname, error);
7640a5de
LP
532}
533
ebcf1f97
LP
534static int method_set_icon_name(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
535 return set_machine_info(userdata, bus, m, PROP_ICON_NAME, method_set_icon_name, error);
66a4c743
LP
536}
537
ebcf1f97
LP
538static int method_set_chassis(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
539 return set_machine_info(userdata, bus, m, PROP_CHASSIS, method_set_chassis, error);
66a4c743
LP
540}
541
542static const sd_bus_vtable hostname_vtable[] = {
543 SD_BUS_VTABLE_START(0),
544 SD_BUS_PROPERTY("Hostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_HOSTNAME, 0),
545 SD_BUS_PROPERTY("StaticHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_STATIC_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
546 SD_BUS_PROPERTY("PrettyHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
547 SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
548 SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
adacb957
LP
549 SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
550 SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
551 SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, SD_BUS_VTABLE_UNPRIVILEGED),
552 SD_BUS_METHOD("SetIconName", "sb", NULL, method_set_icon_name, SD_BUS_VTABLE_UNPRIVILEGED),
553 SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED),
66a4c743
LP
554 SD_BUS_VTABLE_END,
555};
556
557static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
558 _cleanup_bus_unref_ sd_bus *bus = NULL;
7640a5de
LP
559 int r;
560
66a4c743
LP
561 assert(c);
562 assert(event);
d0baa06f
LP
563 assert(_bus);
564
76b54375 565 r = sd_bus_default_system(&bus);
66a4c743
LP
566 if (r < 0) {
567 log_error("Failed to get system bus connection: %s", strerror(-r));
568 return r;
d0baa06f
LP
569 }
570
66a4c743
LP
571 r = sd_bus_add_object_vtable(bus, "/org/freedesktop/hostname1", "org.freedesktop.hostname1", hostname_vtable, c);
572 if (r < 0) {
573 log_error("Failed to register object: %s", strerror(-r));
574 return r;
d0baa06f
LP
575 }
576
5bb658a1 577 r = sd_bus_request_name(bus, "org.freedesktop.hostname1", 0);
66a4c743
LP
578 if (r < 0) {
579 log_error("Failed to register name: %s", strerror(-r));
580 return r;
add10b5a
LP
581 }
582
66a4c743
LP
583 r = sd_bus_attach_event(bus, event, 0);
584 if (r < 0) {
585 log_error("Failed to attach bus to event loop: %s", strerror(-r));
586 return r;
587 }
d0baa06f 588
66a4c743
LP
589 *_bus = bus;
590 bus = NULL;
d0baa06f 591
66a4c743 592 return 0;
d0baa06f
LP
593}
594
595int main(int argc, char *argv[]) {
66a4c743
LP
596 Context context = {};
597
598 _cleanup_event_unref_ sd_event *event = NULL;
599 _cleanup_bus_unref_ sd_bus *bus = NULL;
d0baa06f 600 int r;
d0baa06f 601
7640a5de
LP
602 log_set_target(LOG_TARGET_AUTO);
603 log_parse_environment();
604 log_open();
605
4c12626c 606 umask(0022);
a5c32cff 607 label_init("/etc");
4c12626c 608
7640a5de
LP
609 if (argc != 1) {
610 log_error("This program takes no arguments.");
611 r = -EINVAL;
612 goto finish;
613 }
614
c2a14cf0
LP
615 if (!check_nss())
616 log_warning("Warning: nss-myhostname is not installed. Changing the local hostname might make it unresolveable. Please install nss-myhostname!");
617
66a4c743
LP
618 if (argc != 1) {
619 log_error("This program takes no arguments.");
620 r = -EINVAL;
621 goto finish;
622 }
623
afc6adb5 624 r = sd_event_default(&event);
7640a5de 625 if (r < 0) {
66a4c743 626 log_error("Failed to allocate event loop: %s", strerror(-r));
7640a5de
LP
627 goto finish;
628 }
629
cde93897
LP
630 sd_event_set_watchdog(event, true);
631
66a4c743 632 r = connect_bus(&context, event, &bus);
d0baa06f 633 if (r < 0)
7640a5de 634 goto finish;
7640a5de 635
66a4c743
LP
636 r = context_read_data(&context);
637 if (r < 0) {
638 log_error("Failed to read timezone data: %s", strerror(-r));
639 goto finish;
640 }
ad740100 641
66a4c743
LP
642 r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC);
643 if (r < 0) {
644 log_error("Failed to run event loop: %s", strerror(-r));
645 goto finish;
ad740100 646 }
7640a5de 647
7640a5de 648finish:
66a4c743 649 context_free(&context, bus);
7640a5de 650
7640a5de
LP
651 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
652}