~ubuntu-branches/debian/jessie/systemd/jessie

« back to all changes in this revision

Viewing changes to src/hostname/hostnamed.c

  • Committer: Package Import Robot
  • Author(s): Tollef Fog Heen, Tollef Fog Heen, Michael Biebl
  • Date: 2012-04-03 19:59:17 UTC
  • mfrom: (1.1.10) (6.1.3 experimental)
  • Revision ID: package-import@ubuntu.com-20120403195917-l532urrbg4pkreas
Tags: 44-1
[ Tollef Fog Heen ]
* New upstream version.
  - Backport 3492207: journal: PAGE_SIZE is not known on ppc and other
    archs
  - Backport 5a2a2a1: journal: react with immediate rotation to a couple
    of more errors
  - Backport 693ce21: util: never follow symlinks in rm_rf_children()
    Fixes CVE-2012-1174, closes: #664364
* Drop output message from init-functions hook, it's pointless.
* Only rmdir /lib/init/rw if it exists.
* Explicitly order debian-fixup before sysinit.target to prevent a
  possible race condition with the creation of sockets.  Thanks to
  Michael Biebl for debugging this.
* Always restart the initctl socket on upgrades, to mask sysvinit
  removing it.

[ Michael Biebl ]
* Remove workaround for non-interactive sessions from pam config again.
* Create compat /dev/initctl symlink in case we are upgrading from a system
  running a newer version of sysvinit (using /run/initctl) and sysvinit is
  replaced with systemd-sysv during the upgrade. Closes: #663219
* Install new man pages.
* Build-Depend on valac (>= 0.12) instead of valac-0.12. Closes: #663323

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
 
2
 
 
3
/***
 
4
  This file is part of systemd.
 
5
 
 
6
  Copyright 2011 Lennart Poettering
 
7
 
 
8
  systemd is free software; you can redistribute it and/or modify it
 
9
  under the terms of the GNU General Public License as published by
 
10
  the Free Software Foundation; either version 2 of the License, or
 
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
 
16
  General Public License for more details.
 
17
 
 
18
  You should have received a copy of the GNU General Public License
 
19
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 
20
***/
 
21
 
 
22
#include <dbus/dbus.h>
 
23
 
 
24
#include <errno.h>
 
25
#include <string.h>
 
26
#include <unistd.h>
 
27
#include <dlfcn.h>
 
28
 
 
29
#include "util.h"
 
30
#include "strv.h"
 
31
#include "dbus-common.h"
 
32
#include "polkit.h"
 
33
#include "def.h"
 
34
#include "virt.h"
 
35
 
 
36
#define INTERFACE \
 
37
        " <interface name=\"org.freedesktop.hostname1\">\n"             \
 
38
        "  <property name=\"Hostname\" type=\"s\" access=\"read\"/>\n"  \
 
39
        "  <property name=\"StaticHostname\" type=\"s\" access=\"read\"/>\n" \
 
40
        "  <property name=\"PrettyHostname\" type=\"s\" access=\"read\"/>\n" \
 
41
        "  <property name=\"IconName\" type=\"s\" access=\"read\"/>\n"  \
 
42
        "  <method name=\"SetHostname\">\n"                             \
 
43
        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
 
44
        "   <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
 
45
        "  </method>\n"                                                 \
 
46
        "  <method name=\"SetStaticHostname\">\n"                       \
 
47
        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
 
48
        "   <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
 
49
        "  </method>\n"                                                 \
 
50
        "  <method name=\"SetPrettyHostname\">\n"                       \
 
51
        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
 
52
        "   <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
 
53
        "  </method>\n"                                                 \
 
54
        "  <method name=\"SetIconName\">\n"                             \
 
55
        "   <arg name=\"name\" type=\"s\" direction=\"in\"/>\n"         \
 
56
        "   <arg name=\"user_interaction\" type=\"b\" direction=\"in\"/>\n" \
 
57
        "  </method>\n"                                                 \
 
58
        " </interface>\n"
 
59
 
 
60
#define INTROSPECTION                                                   \
 
61
        DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
 
62
        "<node>\n"                                                      \
 
63
        INTERFACE                                                       \
 
64
        BUS_PROPERTIES_INTERFACE                                        \
 
65
        BUS_INTROSPECTABLE_INTERFACE                                    \
 
66
        BUS_PEER_INTERFACE                                              \
 
67
        "</node>\n"
 
68
 
 
69
#define INTERFACES_LIST                         \
 
70
        BUS_GENERIC_INTERFACES_LIST             \
 
71
        "org.freedesktop.hostname1\0"
 
72
 
 
73
const char hostname_interface[] _introspect_("hostname1") = INTERFACE;
 
74
 
 
75
enum {
 
76
        PROP_HOSTNAME,
 
77
        PROP_STATIC_HOSTNAME,
 
78
        PROP_PRETTY_HOSTNAME,
 
79
        PROP_ICON_NAME,
 
80
        _PROP_MAX
 
81
};
 
82
 
 
83
static char *data[_PROP_MAX] = {
 
84
        NULL,
 
85
        NULL,
 
86
        NULL,
 
87
        NULL
 
88
};
 
89
 
 
90
static usec_t remain_until = 0;
 
91
 
 
92
static void free_data(void) {
 
93
        int p;
 
94
 
 
95
        for (p = 0; p < _PROP_MAX; p++) {
 
96
                free(data[p]);
 
97
                data[p] = NULL;
 
98
        }
 
99
}
 
100
 
 
101
static int read_data(void) {
 
102
        int r;
 
103
 
 
104
        free_data();
 
105
 
 
106
        data[PROP_HOSTNAME] = gethostname_malloc();
 
107
        if (!data[PROP_HOSTNAME])
 
108
                return -ENOMEM;
 
109
 
 
110
        r = read_one_line_file("/etc/hostname", &data[PROP_STATIC_HOSTNAME]);
 
111
        if (r < 0 && r != -ENOENT)
 
112
                return r;
 
113
 
 
114
        r = parse_env_file("/etc/machine-info", NEWLINE,
 
115
                           "PRETTY_HOSTNAME", &data[PROP_PRETTY_HOSTNAME],
 
116
                           "ICON_NAME", &data[PROP_ICON_NAME],
 
117
                           NULL);
 
118
        if (r < 0 && r != -ENOENT)
 
119
                return r;
 
120
 
 
121
        return 0;
 
122
}
 
123
 
 
124
static bool check_nss(void) {
 
125
 
 
126
        void *dl;
 
127
 
 
128
        if ((dl = dlopen("libnss_myhostname.so.2", RTLD_LAZY))) {
 
129
                dlclose(dl);
 
130
                return true;
 
131
        }
 
132
 
 
133
        return false;
 
134
}
 
135
 
 
136
static const char* fallback_icon_name(void) {
 
137
 
 
138
#if defined(__i386__) || defined(__x86_64__)
 
139
        int r;
 
140
        char *type;
 
141
        unsigned t;
 
142
#endif
 
143
 
 
144
        if (detect_virtualization(NULL) > 0)
 
145
                return "computer-vm";
 
146
 
 
147
#if defined(__i386__) || defined(__x86_64__)
 
148
        r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
 
149
        if (r < 0)
 
150
                return NULL;
 
151
 
 
152
        r = safe_atou(type, &t);
 
153
        free(type);
 
154
 
 
155
        if (r < 0)
 
156
                return NULL;
 
157
 
 
158
        /* We only list the really obvious cases here. The DMI data is
 
159
           unreliable enough, so let's not do any additional guesswork
 
160
           on top of that.
 
161
 
 
162
           See the SMBIOS Specification 2.7.1 section 7.4.1 for
 
163
           details about the values listed here:
 
164
 
 
165
           http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf
 
166
         */
 
167
 
 
168
        switch (t) {
 
169
 
 
170
        case 0x3:
 
171
        case 0x4:
 
172
        case 0x6:
 
173
        case 0x7:
 
174
                return "computer-desktop";
 
175
 
 
176
        case 0x9:
 
177
        case 0xA:
 
178
        case 0xE:
 
179
                return "computer-laptop";
 
180
 
 
181
        case 0x11:
 
182
        case 0x1C:
 
183
                return "computer-server";
 
184
        }
 
185
 
 
186
#endif
 
187
        return NULL;
 
188
}
 
189
 
 
190
static int write_data_hostname(void) {
 
191
        const char *hn;
 
192
 
 
193
        if (isempty(data[PROP_HOSTNAME]))
 
194
                hn = "localhost";
 
195
        else
 
196
                hn = data[PROP_HOSTNAME];
 
197
 
 
198
        if (sethostname(hn, strlen(hn)) < 0)
 
199
                return -errno;
 
200
 
 
201
        return 0;
 
202
}
 
203
 
 
204
static int write_data_static_hostname(void) {
 
205
 
 
206
        if (isempty(data[PROP_STATIC_HOSTNAME])) {
 
207
 
 
208
                if (unlink("/etc/hostname") < 0)
 
209
                        return errno == ENOENT ? 0 : -errno;
 
210
 
 
211
                return 0;
 
212
        }
 
213
 
 
214
        return write_one_line_file_atomic("/etc/hostname", data[PROP_STATIC_HOSTNAME]);
 
215
}
 
216
 
 
217
static int write_data_other(void) {
 
218
 
 
219
        static const char * const name[_PROP_MAX] = {
 
220
                [PROP_PRETTY_HOSTNAME] = "PRETTY_HOSTNAME",
 
221
                [PROP_ICON_NAME] = "ICON_NAME"
 
222
        };
 
223
 
 
224
        char **l = NULL;
 
225
        int r, p;
 
226
 
 
227
        r = load_env_file("/etc/machine-info", &l);
 
228
        if (r < 0 && r != -ENOENT)
 
229
                return r;
 
230
 
 
231
        for (p = 2; p < _PROP_MAX; p++) {
 
232
                char *t, **u;
 
233
 
 
234
                assert(name[p]);
 
235
 
 
236
                if (isempty(data[p]))  {
 
237
                        strv_env_unset(l, name[p]);
 
238
                        continue;
 
239
                }
 
240
 
 
241
                if (asprintf(&t, "%s=%s", name[p], strempty(data[p])) < 0) {
 
242
                        strv_free(l);
 
243
                        return -ENOMEM;
 
244
                }
 
245
 
 
246
                u = strv_env_set(l, t);
 
247
                free(t);
 
248
                strv_free(l);
 
249
 
 
250
                if (!u)
 
251
                        return -ENOMEM;
 
252
                l = u;
 
253
        }
 
254
 
 
255
        if (strv_isempty(l)) {
 
256
 
 
257
                if (unlink("/etc/machine-info") < 0)
 
258
                        return errno == ENOENT ? 0 : -errno;
 
259
 
 
260
                return 0;
 
261
        }
 
262
 
 
263
        r = write_env_file("/etc/machine-info", l);
 
264
        strv_free(l);
 
265
 
 
266
        return r;
 
267
}
 
268
 
 
269
static int bus_hostname_append_icon_name(DBusMessageIter *i, const char *property, void *userdata) {
 
270
        const char *name;
 
271
 
 
272
        assert(i);
 
273
        assert(property);
 
274
 
 
275
        if (isempty(data[PROP_ICON_NAME]))
 
276
                name = fallback_icon_name();
 
277
        else
 
278
                name = data[PROP_ICON_NAME];
 
279
 
 
280
        return bus_property_append_string(i, property, (void*) name);
 
281
}
 
282
 
 
283
static const BusProperty bus_hostname_properties[] = {
 
284
        { "Hostname",       bus_property_append_string,    "s", sizeof(data[0])*PROP_HOSTNAME,        true },
 
285
        { "StaticHostname", bus_property_append_string,    "s", sizeof(data[0])*PROP_STATIC_HOSTNAME, true },
 
286
        { "PrettyHostname", bus_property_append_string,    "s", sizeof(data[0])*PROP_PRETTY_HOSTNAME, true },
 
287
        { "IconName",       bus_hostname_append_icon_name, "s", sizeof(data[0])*PROP_ICON_NAME,       true },
 
288
        { NULL, }
 
289
};
 
290
 
 
291
static const BusBoundProperties bps[] = {
 
292
        { "org.freedesktop.hostname1", bus_hostname_properties, data },
 
293
        { NULL, }
 
294
};
 
295
 
 
296
static DBusHandlerResult hostname_message_handler(
 
297
                DBusConnection *connection,
 
298
                DBusMessage *message,
 
299
                void *userdata) {
 
300
 
 
301
 
 
302
        DBusMessage *reply = NULL, *changed = NULL;
 
303
        DBusError error;
 
304
        int r;
 
305
 
 
306
        assert(connection);
 
307
        assert(message);
 
308
 
 
309
        dbus_error_init(&error);
 
310
 
 
311
        if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetHostname")) {
 
312
                const char *name;
 
313
                dbus_bool_t interactive;
 
314
 
 
315
                if (!dbus_message_get_args(
 
316
                                    message,
 
317
                                    &error,
 
318
                                    DBUS_TYPE_STRING, &name,
 
319
                                    DBUS_TYPE_BOOLEAN, &interactive,
 
320
                                    DBUS_TYPE_INVALID))
 
321
                        return bus_send_error_reply(connection, message, &error, -EINVAL);
 
322
 
 
323
                if (isempty(name))
 
324
                        name = data[PROP_STATIC_HOSTNAME];
 
325
 
 
326
                if (isempty(name))
 
327
                        name = "localhost";
 
328
 
 
329
                if (!hostname_is_valid(name))
 
330
                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
 
331
 
 
332
                if (!streq_ptr(name, data[PROP_HOSTNAME])) {
 
333
                        char *h;
 
334
 
 
335
                        r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-hostname", interactive, NULL, &error);
 
336
                        if (r < 0)
 
337
                                return bus_send_error_reply(connection, message, &error, r);
 
338
 
 
339
                        h = strdup(name);
 
340
                        if (!h)
 
341
                                goto oom;
 
342
 
 
343
                        free(data[PROP_HOSTNAME]);
 
344
                        data[PROP_HOSTNAME] = h;
 
345
 
 
346
                        r = write_data_hostname();
 
347
                        if (r < 0) {
 
348
                                log_error("Failed to set host name: %s", strerror(-r));
 
349
                                return bus_send_error_reply(connection, message, NULL, r);
 
350
                        }
 
351
 
 
352
                        log_info("Changed host name to '%s'", strempty(data[PROP_HOSTNAME]));
 
353
 
 
354
                        changed = bus_properties_changed_new(
 
355
                                        "/org/freedesktop/hostname1",
 
356
                                        "org.freedesktop.hostname1",
 
357
                                        "Hostname\0");
 
358
                        if (!changed)
 
359
                                goto oom;
 
360
                }
 
361
 
 
362
        } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetStaticHostname")) {
 
363
                const char *name;
 
364
                dbus_bool_t interactive;
 
365
 
 
366
                if (!dbus_message_get_args(
 
367
                                    message,
 
368
                                    &error,
 
369
                                    DBUS_TYPE_STRING, &name,
 
370
                                    DBUS_TYPE_BOOLEAN, &interactive,
 
371
                                    DBUS_TYPE_INVALID))
 
372
                        return bus_send_error_reply(connection, message, &error, -EINVAL);
 
373
 
 
374
                if (isempty(name))
 
375
                        name = NULL;
 
376
 
 
377
                if (!streq_ptr(name, data[PROP_STATIC_HOSTNAME])) {
 
378
 
 
379
                        r = verify_polkit(connection, message, "org.freedesktop.hostname1.set-static-hostname", interactive, NULL, &error);
 
380
                        if (r < 0)
 
381
                                return bus_send_error_reply(connection, message, &error, r);
 
382
 
 
383
                        if (isempty(name)) {
 
384
                                free(data[PROP_STATIC_HOSTNAME]);
 
385
                                data[PROP_STATIC_HOSTNAME] = NULL;
 
386
                        } else {
 
387
                                char *h;
 
388
 
 
389
                                if (!hostname_is_valid(name))
 
390
                                        return bus_send_error_reply(connection, message, NULL, -EINVAL);
 
391
 
 
392
                                h = strdup(name);
 
393
                                if (!h)
 
394
                                        goto oom;
 
395
 
 
396
                                free(data[PROP_STATIC_HOSTNAME]);
 
397
                                data[PROP_STATIC_HOSTNAME] = h;
 
398
                        }
 
399
 
 
400
                        r = write_data_static_hostname();
 
401
                        if (r < 0) {
 
402
                                log_error("Failed to write static host name: %s", strerror(-r));
 
403
                                return bus_send_error_reply(connection, message, NULL, r);
 
404
                        }
 
405
 
 
406
                        log_info("Changed static host name to '%s'", strempty(data[PROP_STATIC_HOSTNAME]));
 
407
 
 
408
                        changed = bus_properties_changed_new(
 
409
                                        "/org/freedesktop/hostname1",
 
410
                                        "org.freedesktop.hostname1",
 
411
                                        "StaticHostname\0");
 
412
                        if (!changed)
 
413
                                goto oom;
 
414
                }
 
415
 
 
416
        } else if (dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetPrettyHostname") ||
 
417
                   dbus_message_is_method_call(message, "org.freedesktop.hostname1", "SetIconName")) {
 
418
 
 
419
                const char *name;
 
420
                dbus_bool_t interactive;
 
421
                int k;
 
422
 
 
423
                if (!dbus_message_get_args(
 
424
                                    message,
 
425
                                    &error,
 
426
                                    DBUS_TYPE_STRING, &name,
 
427
                                    DBUS_TYPE_BOOLEAN, &interactive,
 
428
                                    DBUS_TYPE_INVALID))
 
429
                        return bus_send_error_reply(connection, message, &error, -EINVAL);
 
430
 
 
431
                if (isempty(name))
 
432
                        name = NULL;
 
433
 
 
434
                k = streq(dbus_message_get_member(message), "SetPrettyHostname") ? PROP_PRETTY_HOSTNAME : PROP_ICON_NAME;
 
435
 
 
436
                if (!streq_ptr(name, data[k])) {
 
437
 
 
438
                        /* Since the pretty hostname should always be
 
439
                         * changed at the same time as the static one,
 
440
                         * use the same policy action for both... */
 
441
 
 
442
                        r = verify_polkit(connection, message, k == PROP_PRETTY_HOSTNAME ?
 
443
                                          "org.freedesktop.hostname1.set-static-hostname" :
 
444
                                          "org.freedesktop.hostname1.set-machine-info", interactive, NULL, &error);
 
445
                        if (r < 0)
 
446
                                return bus_send_error_reply(connection, message, &error, r);
 
447
 
 
448
                        if (isempty(name)) {
 
449
                                free(data[k]);
 
450
                                data[k] = NULL;
 
451
                        } else {
 
452
                                char *h;
 
453
 
 
454
                                h = strdup(name);
 
455
                                if (!h)
 
456
                                        goto oom;
 
457
 
 
458
                                free(data[k]);
 
459
                                data[k] = h;
 
460
                        }
 
461
 
 
462
                        r = write_data_other();
 
463
                        if (r < 0) {
 
464
                                log_error("Failed to write machine info: %s", strerror(-r));
 
465
                                return bus_send_error_reply(connection, message, NULL, r);
 
466
                        }
 
467
 
 
468
                        log_info("Changed %s to '%s'", k == PROP_PRETTY_HOSTNAME ? "pretty host name" : "icon name", strempty(data[k]));
 
469
 
 
470
                        changed = bus_properties_changed_new(
 
471
                                        "/org/freedesktop/hostname1",
 
472
                                        "org.freedesktop.hostname1",
 
473
                                        k == PROP_PRETTY_HOSTNAME ? "PrettyHostname\0" : "IconName\0");
 
474
                        if (!changed)
 
475
                                goto oom;
 
476
                }
 
477
 
 
478
        } else
 
479
                return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
 
480
 
 
481
        if (!(reply = dbus_message_new_method_return(message)))
 
482
                goto oom;
 
483
 
 
484
        if (!dbus_connection_send(connection, reply, NULL))
 
485
                goto oom;
 
486
 
 
487
        dbus_message_unref(reply);
 
488
        reply = NULL;
 
489
 
 
490
        if (changed) {
 
491
 
 
492
                if (!dbus_connection_send(connection, changed, NULL))
 
493
                        goto oom;
 
494
 
 
495
                dbus_message_unref(changed);
 
496
        }
 
497
 
 
498
        return DBUS_HANDLER_RESULT_HANDLED;
 
499
 
 
500
oom:
 
501
        if (reply)
 
502
                dbus_message_unref(reply);
 
503
 
 
504
        if (changed)
 
505
                dbus_message_unref(changed);
 
506
 
 
507
        dbus_error_free(&error);
 
508
 
 
509
        return DBUS_HANDLER_RESULT_NEED_MEMORY;
 
510
}
 
511
 
 
512
static int connect_bus(DBusConnection **_bus) {
 
513
        static const DBusObjectPathVTable hostname_vtable = {
 
514
                .message_function = hostname_message_handler
 
515
        };
 
516
        DBusError error;
 
517
        DBusConnection *bus = NULL;
 
518
        int r;
 
519
 
 
520
        assert(_bus);
 
521
 
 
522
        dbus_error_init(&error);
 
523
 
 
524
        bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
 
525
        if (!bus) {
 
526
                log_error("Failed to get system D-Bus connection: %s", bus_error_message(&error));
 
527
                r = -ECONNREFUSED;
 
528
                goto fail;
 
529
        }
 
530
 
 
531
        dbus_connection_set_exit_on_disconnect(bus, FALSE);
 
532
 
 
533
        if (!dbus_connection_register_object_path(bus, "/org/freedesktop/hostname1", &hostname_vtable, NULL) ||
 
534
            !dbus_connection_add_filter(bus, bus_exit_idle_filter, &remain_until, NULL)) {
 
535
                log_error("Not enough memory");
 
536
                r = -ENOMEM;
 
537
                goto fail;
 
538
        }
 
539
 
 
540
        r = dbus_bus_request_name(bus, "org.freedesktop.hostname1", DBUS_NAME_FLAG_DO_NOT_QUEUE, &error);
 
541
        if (dbus_error_is_set(&error)) {
 
542
                log_error("Failed to register name on bus: %s", bus_error_message(&error));
 
543
                r = -EEXIST;
 
544
                goto fail;
 
545
        }
 
546
 
 
547
        if (r != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
 
548
                log_error("Failed to acquire name.");
 
549
                r = -EEXIST;
 
550
                goto fail;
 
551
        }
 
552
 
 
553
        if (_bus)
 
554
                *_bus = bus;
 
555
 
 
556
        return 0;
 
557
 
 
558
fail:
 
559
        dbus_connection_close(bus);
 
560
        dbus_connection_unref(bus);
 
561
 
 
562
        dbus_error_free(&error);
 
563
 
 
564
        return r;
 
565
}
 
566
 
 
567
int main(int argc, char *argv[]) {
 
568
        int r;
 
569
        DBusConnection *bus = NULL;
 
570
        bool exiting = false;
 
571
 
 
572
        log_set_target(LOG_TARGET_AUTO);
 
573
        log_parse_environment();
 
574
        log_open();
 
575
 
 
576
        umask(0022);
 
577
 
 
578
        if (argc == 2 && streq(argv[1], "--introspect")) {
 
579
                fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
 
580
                      "<node>\n", stdout);
 
581
                fputs(hostname_interface, stdout);
 
582
                fputs("</node>\n", stdout);
 
583
                return 0;
 
584
        }
 
585
 
 
586
        if (argc != 1) {
 
587
                log_error("This program takes no arguments.");
 
588
                r = -EINVAL;
 
589
                goto finish;
 
590
        }
 
591
 
 
592
        if (!check_nss())
 
593
                log_warning("Warning: nss-myhostname is not installed. Changing the local hostname might make it unresolveable. Please install nss-myhostname!");
 
594
 
 
595
        r = read_data();
 
596
        if (r < 0) {
 
597
                log_error("Failed to read hostname data: %s", strerror(-r));
 
598
                goto finish;
 
599
        }
 
600
 
 
601
        r = connect_bus(&bus);
 
602
        if (r < 0)
 
603
                goto finish;
 
604
 
 
605
        remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
 
606
        for (;;) {
 
607
 
 
608
                if (!dbus_connection_read_write_dispatch(bus, exiting ? -1 : (int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC)))
 
609
                        break;
 
610
 
 
611
                if (!exiting && remain_until < now(CLOCK_MONOTONIC)) {
 
612
                        exiting = true;
 
613
                        bus_async_unregister_and_exit(bus, "org.freedesktop.hostname1");
 
614
                }
 
615
        }
 
616
 
 
617
        r = 0;
 
618
 
 
619
finish:
 
620
        free_data();
 
621
 
 
622
        if (bus) {
 
623
                dbus_connection_flush(bus);
 
624
                dbus_connection_close(bus);
 
625
                dbus_connection_unref(bus);
 
626
        }
 
627
 
 
628
        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 
629
}