chiark / gitweb /
Fix possible lack of status messages on shutdown/reboot
[elogind.git] / src / core / dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
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
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   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/epoll.h>
23 #include <sys/timerfd.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <dbus/dbus.h>
27
28 #include "dbus.h"
29 #include "log.h"
30 #include "strv.h"
31 #include "mkdir.h"
32 #include "missing.h"
33 #include "dbus-unit.h"
34 #include "dbus-job.h"
35 #include "dbus-manager.h"
36 #include "dbus-service.h"
37 #include "dbus-socket.h"
38 #include "dbus-target.h"
39 #include "dbus-device.h"
40 #include "dbus-mount.h"
41 #include "dbus-automount.h"
42 #include "dbus-snapshot.h"
43 #include "dbus-swap.h"
44 #include "dbus-timer.h"
45 #include "dbus-path.h"
46 #include "bus-errors.h"
47 #include "special.h"
48 #include "dbus-common.h"
49
50 #define CONNECTIONS_MAX 512
51
52 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */
53 #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
54 /* Only used as a fallback */
55 #define DBUS_SESSION_BUS_DEFAULT_ADDRESS "autolaunch:"
56
57 static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE;
58 static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE;
59
60 const char *const bus_interface_table[] = {
61         "org.freedesktop.DBus.Properties",     bus_properties_interface,
62         "org.freedesktop.DBus.Introspectable", bus_introspectable_interface,
63         "org.freedesktop.systemd1.Manager",    bus_manager_interface,
64         "org.freedesktop.systemd1.Job",        bus_job_interface,
65         "org.freedesktop.systemd1.Unit",       bus_unit_interface,
66         "org.freedesktop.systemd1.Service",    bus_service_interface,
67         "org.freedesktop.systemd1.Socket",     bus_socket_interface,
68         "org.freedesktop.systemd1.Target",     bus_target_interface,
69         "org.freedesktop.systemd1.Device",     bus_device_interface,
70         "org.freedesktop.systemd1.Mount",      bus_mount_interface,
71         "org.freedesktop.systemd1.Automount",  bus_automount_interface,
72         "org.freedesktop.systemd1.Snapshot",   bus_snapshot_interface,
73         "org.freedesktop.systemd1.Swap",       bus_swap_interface,
74         "org.freedesktop.systemd1.Timer",      bus_timer_interface,
75         "org.freedesktop.systemd1.Path",       bus_path_interface,
76         NULL
77 };
78
79 static void bus_done_api(Manager *m);
80 static void bus_done_system(Manager *m);
81 static void bus_done_private(Manager *m);
82 static void shutdown_connection(Manager *m, DBusConnection *c);
83
84 static void bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data)  {
85         Manager *m = data;
86
87         assert(bus);
88         assert(m);
89
90         /* We maintain two sets, one for those connections where we
91          * requested a dispatch, and another where we didn't. And then,
92          * we move the connections between the two sets. */
93
94         if (status == DBUS_DISPATCH_COMPLETE)
95                 set_move_one(m->bus_connections, m->bus_connections_for_dispatch, bus);
96         else
97                 set_move_one(m->bus_connections_for_dispatch, m->bus_connections, bus);
98 }
99
100 void bus_watch_event(Manager *m, Watch *w, int events) {
101         assert(m);
102         assert(w);
103
104         /* This is called by the event loop whenever there is
105          * something happening on D-Bus' file handles. */
106
107         if (!dbus_watch_get_enabled(w->data.bus_watch))
108                 return;
109
110         dbus_watch_handle(w->data.bus_watch, bus_events_to_flags(events));
111 }
112
113 static dbus_bool_t bus_add_watch(DBusWatch *bus_watch, void *data) {
114         Manager *m = data;
115         Watch *w;
116         struct epoll_event ev;
117
118         assert(bus_watch);
119         assert(m);
120
121         if (!(w = new0(Watch, 1)))
122                 return FALSE;
123
124         w->fd = dbus_watch_get_unix_fd(bus_watch);
125         w->type = WATCH_DBUS_WATCH;
126         w->data.bus_watch = bus_watch;
127
128         zero(ev);
129         ev.events = bus_flags_to_events(bus_watch);
130         ev.data.ptr = w;
131
132         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
133
134                 if (errno != EEXIST) {
135                         free(w);
136                         return FALSE;
137                 }
138
139                 /* Hmm, bloody D-Bus creates multiple watches on the
140                  * same fd. epoll() does not like that. As a dirty
141                  * hack we simply dup() the fd and hence get a second
142                  * one we can safely add to the epoll(). */
143
144                 if ((w->fd = dup(w->fd)) < 0) {
145                         free(w);
146                         return FALSE;
147                 }
148
149                 if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0) {
150                         close_nointr_nofail(w->fd);
151                         free(w);
152                         return FALSE;
153                 }
154
155                 w->fd_is_dupped = true;
156         }
157
158         dbus_watch_set_data(bus_watch, w, NULL);
159
160         return TRUE;
161 }
162
163 static void bus_remove_watch(DBusWatch *bus_watch, void *data) {
164         Manager *m = data;
165         Watch *w;
166
167         assert(bus_watch);
168         assert(m);
169
170         w = dbus_watch_get_data(bus_watch);
171         if (!w)
172                 return;
173
174         assert(w->type == WATCH_DBUS_WATCH);
175         assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
176
177         if (w->fd_is_dupped)
178                 close_nointr_nofail(w->fd);
179
180         free(w);
181 }
182
183 static void bus_toggle_watch(DBusWatch *bus_watch, void *data) {
184         Manager *m = data;
185         Watch *w;
186         struct epoll_event ev;
187
188         assert(bus_watch);
189         assert(m);
190
191         w = dbus_watch_get_data(bus_watch);
192         if (!w)
193                 return;
194
195         assert(w->type == WATCH_DBUS_WATCH);
196
197         zero(ev);
198         ev.events = bus_flags_to_events(bus_watch);
199         ev.data.ptr = w;
200
201         assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_MOD, w->fd, &ev) == 0);
202 }
203
204 static int bus_timeout_arm(Manager *m, Watch *w) {
205         struct itimerspec its = {};
206
207         assert(m);
208         assert(w);
209
210         if (dbus_timeout_get_enabled(w->data.bus_timeout)) {
211                 timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC);
212                 its.it_interval = its.it_value;
213         }
214
215         if (timerfd_settime(w->fd, 0, &its, NULL) < 0)
216                 return -errno;
217
218         return 0;
219 }
220
221 void bus_timeout_event(Manager *m, Watch *w, int events) {
222         assert(m);
223         assert(w);
224
225         /* This is called by the event loop whenever there is
226          * something happening on D-Bus' file handles. */
227
228         if (!(dbus_timeout_get_enabled(w->data.bus_timeout)))
229                 return;
230
231         dbus_timeout_handle(w->data.bus_timeout);
232 }
233
234 static dbus_bool_t bus_add_timeout(DBusTimeout *timeout, void *data) {
235         Manager *m = data;
236         Watch *w;
237         struct epoll_event ev;
238
239         assert(timeout);
240         assert(m);
241
242         if (!(w = new0(Watch, 1)))
243                 return FALSE;
244
245         if ((w->fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0)
246                 goto fail;
247
248         w->type = WATCH_DBUS_TIMEOUT;
249         w->data.bus_timeout = timeout;
250
251         if (bus_timeout_arm(m, w) < 0)
252                 goto fail;
253
254         zero(ev);
255         ev.events = EPOLLIN;
256         ev.data.ptr = w;
257
258         if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, w->fd, &ev) < 0)
259                 goto fail;
260
261         dbus_timeout_set_data(timeout, w, NULL);
262
263         return TRUE;
264
265 fail:
266         if (w->fd >= 0)
267                 close_nointr_nofail(w->fd);
268
269         free(w);
270         return FALSE;
271 }
272
273 static void bus_remove_timeout(DBusTimeout *timeout, void *data) {
274         Manager *m = data;
275         Watch *w;
276
277         assert(timeout);
278         assert(m);
279
280         w = dbus_timeout_get_data(timeout);
281         if (!w)
282                 return;
283
284         assert(w->type == WATCH_DBUS_TIMEOUT);
285
286         assert_se(epoll_ctl(m->epoll_fd, EPOLL_CTL_DEL, w->fd, NULL) >= 0);
287         close_nointr_nofail(w->fd);
288         free(w);
289 }
290
291 static void bus_toggle_timeout(DBusTimeout *timeout, void *data) {
292         Manager *m = data;
293         Watch *w;
294         int r;
295
296         assert(timeout);
297         assert(m);
298
299         w = dbus_timeout_get_data(timeout);
300         if (!w)
301                 return;
302
303         assert(w->type == WATCH_DBUS_TIMEOUT);
304
305         if ((r = bus_timeout_arm(m, w)) < 0)
306                 log_error("Failed to rearm timer: %s", strerror(-r));
307 }
308
309 static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
310         Manager *m = data;
311         DBusError error;
312         DBusMessage *reply = NULL;
313
314         assert(connection);
315         assert(message);
316         assert(m);
317
318         dbus_error_init(&error);
319
320         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
321             dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
322                 log_debug("Got D-Bus request: %s.%s() on %s",
323                           dbus_message_get_interface(message),
324                           dbus_message_get_member(message),
325                           dbus_message_get_path(message));
326
327         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
328                 log_debug("API D-Bus connection terminated.");
329                 bus_done_api(m);
330
331         } else if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
332                 const char *name, *old_owner, *new_owner;
333
334                 if (!dbus_message_get_args(message, &error,
335                                            DBUS_TYPE_STRING, &name,
336                                            DBUS_TYPE_STRING, &old_owner,
337                                            DBUS_TYPE_STRING, &new_owner,
338                                            DBUS_TYPE_INVALID))
339                         log_error("Failed to parse NameOwnerChanged message: %s", bus_error_message(&error));
340                 else  {
341                         if (set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) name))
342                                 log_debug("Subscription client vanished: %s (left: %u)", name, set_size(BUS_CONNECTION_SUBSCRIBED(m, connection)));
343
344                         if (old_owner[0] == 0)
345                                 old_owner = NULL;
346
347                         if (new_owner[0] == 0)
348                                 new_owner = NULL;
349
350                         manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner);
351                 }
352         } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) {
353                 const char *name;
354
355                 if (!dbus_message_get_args(message, &error,
356                                            DBUS_TYPE_STRING, &name,
357                                            DBUS_TYPE_INVALID))
358                         log_error("Failed to parse ActivationRequest message: %s", bus_error_message(&error));
359                 else  {
360                         int r;
361                         Unit *u;
362
363                         log_debug("Got D-Bus activation request for %s", name);
364
365                         if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) ||
366                             manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) {
367                                 r = -EADDRNOTAVAIL;
368                                 dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down.");
369                         } else {
370                                 r = manager_load_unit(m, name, NULL, &error, &u);
371
372                                 if (r >= 0 && u->refuse_manual_start)
373                                         r = -EPERM;
374
375                                 if (r >= 0)
376                                         r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, &error, NULL);
377                         }
378
379                         if (r < 0) {
380                                 const char *id, *text;
381
382                                 log_debug("D-Bus activation failed for %s: %s", name, strerror(-r));
383
384                                 if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure")))
385                                         goto oom;
386
387                                 id = error.name ? error.name : bus_errno_to_dbus(r);
388                                 text = bus_error(&error, r);
389
390                                 if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) ||
391                                     !dbus_message_append_args(reply,
392                                                               DBUS_TYPE_STRING, &name,
393                                                               DBUS_TYPE_STRING, &id,
394                                                               DBUS_TYPE_STRING, &text,
395                                                               DBUS_TYPE_INVALID))
396                                         goto oom;
397                         }
398
399                         /* On success we don't do anything, the service will be spawned now */
400                 }
401         }
402
403         dbus_error_free(&error);
404
405         if (reply) {
406                 if (!bus_maybe_send_reply(connection, message, reply))
407                         goto oom;
408
409                 dbus_message_unref(reply);
410         }
411
412         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
413
414 oom:
415         if (reply)
416                 dbus_message_unref(reply);
417
418         dbus_error_free(&error);
419
420         return DBUS_HANDLER_RESULT_NEED_MEMORY;
421 }
422
423 static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
424         Manager *m = data;
425         DBusError error;
426
427         assert(connection);
428         assert(message);
429         assert(m);
430
431         dbus_error_init(&error);
432
433         if (m->api_bus != m->system_bus &&
434             (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
435              dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL))
436                 log_debug("Got D-Bus request on system bus: %s.%s() on %s",
437                           dbus_message_get_interface(message),
438                           dbus_message_get_member(message),
439                           dbus_message_get_path(message));
440
441         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
442                 log_debug("System D-Bus connection terminated.");
443                 bus_done_system(m);
444
445         } else if (m->running_as != SYSTEMD_SYSTEM &&
446                    dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
447
448                 const char *cgroup;
449
450                 if (!dbus_message_get_args(message, &error,
451                                            DBUS_TYPE_STRING, &cgroup,
452                                            DBUS_TYPE_INVALID))
453                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
454                 else
455                         manager_notify_cgroup_empty(m, cgroup);
456         }
457
458         dbus_error_free(&error);
459         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
460 }
461
462 static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) {
463         Manager *m = data;
464         DBusError error;
465
466         assert(connection);
467         assert(message);
468         assert(m);
469
470         dbus_error_init(&error);
471
472         if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL ||
473             dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_SIGNAL)
474                 log_debug("Got D-Bus request: %s.%s() on %s",
475                           dbus_message_get_interface(message),
476                           dbus_message_get_member(message),
477                           dbus_message_get_path(message));
478
479         if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected"))
480                 shutdown_connection(m, connection);
481         else if (m->running_as == SYSTEMD_SYSTEM &&
482                  dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
483
484                 const char *cgroup;
485
486                 if (!dbus_message_get_args(message, &error,
487                                            DBUS_TYPE_STRING, &cgroup,
488                                            DBUS_TYPE_INVALID))
489                         log_error("Failed to parse Released message: %s", bus_error_message(&error));
490                 else
491                         manager_notify_cgroup_empty(m, cgroup);
492
493                 /* Forward the message to the system bus, so that user
494                  * instances are notified as well */
495
496                 if (m->system_bus)
497                         dbus_connection_send(m->system_bus, message, NULL);
498         }
499
500         dbus_error_free(&error);
501
502         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
503 }
504
505 unsigned bus_dispatch(Manager *m) {
506         DBusConnection *c;
507
508         assert(m);
509
510         if (m->queued_message) {
511                 /* If we cannot get rid of this message we won't
512                  * dispatch any D-Bus messages, so that we won't end
513                  * up wanting to queue another message. */
514
515                 if (m->queued_message_connection)
516                         if (!dbus_connection_send(m->queued_message_connection, m->queued_message, NULL))
517                                 return 0;
518
519                 dbus_message_unref(m->queued_message);
520                 m->queued_message = NULL;
521                 m->queued_message_connection = NULL;
522         }
523
524         if ((c = set_first(m->bus_connections_for_dispatch))) {
525                 if (dbus_connection_dispatch(c) == DBUS_DISPATCH_COMPLETE)
526                         set_move_one(m->bus_connections, m->bus_connections_for_dispatch, c);
527
528                 return 1;
529         }
530
531         return 0;
532 }
533
534 static void request_name_pending_cb(DBusPendingCall *pending, void *userdata) {
535         DBusMessage *reply;
536         DBusError error;
537
538         dbus_error_init(&error);
539
540         assert_se(reply = dbus_pending_call_steal_reply(pending));
541
542         switch (dbus_message_get_type(reply)) {
543
544         case DBUS_MESSAGE_TYPE_ERROR:
545
546                 assert_se(dbus_set_error_from_message(&error, reply));
547                 log_warning("RequestName() failed: %s", bus_error_message(&error));
548                 break;
549
550         case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
551                 uint32_t r;
552
553                 if (!dbus_message_get_args(reply,
554                                            &error,
555                                            DBUS_TYPE_UINT32, &r,
556                                            DBUS_TYPE_INVALID)) {
557                         log_error("Failed to parse RequestName() reply: %s", bus_error_message(&error));
558                         break;
559                 }
560
561                 if (r == 1)
562                         log_debug("Successfully acquired name.");
563                 else
564                         log_error("Name already owned.");
565
566                 break;
567         }
568
569         default:
570                 assert_not_reached("Invalid reply message");
571         }
572
573         dbus_message_unref(reply);
574         dbus_error_free(&error);
575 }
576
577 static int request_name(Manager *m) {
578         const char *name = "org.freedesktop.systemd1";
579         /* Allow replacing of our name, to ease implementation of
580          * reexecution, where we keep the old connection open until
581          * after the new connection is set up and the name installed
582          * to allow clients to synchronously wait for reexecution to
583          * finish */
584         uint32_t flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT|DBUS_NAME_FLAG_REPLACE_EXISTING;
585         DBusMessage *message = NULL;
586         DBusPendingCall *pending = NULL;
587
588         if (!(message = dbus_message_new_method_call(
589                               DBUS_SERVICE_DBUS,
590                               DBUS_PATH_DBUS,
591                               DBUS_INTERFACE_DBUS,
592                               "RequestName")))
593                 goto oom;
594
595         if (!dbus_message_append_args(
596                             message,
597                             DBUS_TYPE_STRING, &name,
598                             DBUS_TYPE_UINT32, &flags,
599                             DBUS_TYPE_INVALID))
600                 goto oom;
601
602         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
603                 goto oom;
604
605         if (!dbus_pending_call_set_notify(pending, request_name_pending_cb, m, NULL))
606                 goto oom;
607
608         dbus_message_unref(message);
609         dbus_pending_call_unref(pending);
610
611         /* We simple ask for the name and don't wait for it. Sooner or
612          * later we'll have it. */
613
614         return 0;
615
616 oom:
617         if (pending) {
618                 dbus_pending_call_cancel(pending);
619                 dbus_pending_call_unref(pending);
620         }
621
622         if (message)
623                 dbus_message_unref(message);
624
625         return -ENOMEM;
626 }
627
628 static void query_name_list_pending_cb(DBusPendingCall *pending, void *userdata) {
629         DBusMessage *reply;
630         DBusError error;
631         Manager *m = userdata;
632
633         assert(m);
634
635         dbus_error_init(&error);
636
637         assert_se(reply = dbus_pending_call_steal_reply(pending));
638
639         switch (dbus_message_get_type(reply)) {
640
641         case DBUS_MESSAGE_TYPE_ERROR:
642
643                 assert_se(dbus_set_error_from_message(&error, reply));
644                 log_warning("ListNames() failed: %s", bus_error_message(&error));
645                 break;
646
647         case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
648                 int r;
649                 char **l;
650
651                 if ((r = bus_parse_strv(reply, &l)) < 0)
652                         log_warning("Failed to parse ListNames() reply: %s", strerror(-r));
653                 else {
654                         char **t;
655
656                         STRV_FOREACH(t, l)
657                                 /* This is a bit hacky, we say the
658                                  * owner of the name is the name
659                                  * itself, because we don't want the
660                                  * extra traffic to figure out the
661                                  * real owner. */
662                                 manager_dispatch_bus_name_owner_changed(m, *t, NULL, *t);
663
664                         strv_free(l);
665                 }
666
667                 break;
668         }
669
670         default:
671                 assert_not_reached("Invalid reply message");
672         }
673
674         dbus_message_unref(reply);
675         dbus_error_free(&error);
676 }
677
678 static int query_name_list(Manager *m) {
679         DBusMessage *message = NULL;
680         DBusPendingCall *pending = NULL;
681
682         /* Asks for the currently installed bus names */
683
684         if (!(message = dbus_message_new_method_call(
685                               DBUS_SERVICE_DBUS,
686                               DBUS_PATH_DBUS,
687                               DBUS_INTERFACE_DBUS,
688                               "ListNames")))
689                 goto oom;
690
691         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
692                 goto oom;
693
694         if (!dbus_pending_call_set_notify(pending, query_name_list_pending_cb, m, NULL))
695                 goto oom;
696
697         dbus_message_unref(message);
698         dbus_pending_call_unref(pending);
699
700         /* We simple ask for the list and don't wait for it. Sooner or
701          * later we'll get it. */
702
703         return 0;
704
705 oom:
706         if (pending) {
707                 dbus_pending_call_cancel(pending);
708                 dbus_pending_call_unref(pending);
709         }
710
711         if (message)
712                 dbus_message_unref(message);
713
714         return -ENOMEM;
715 }
716
717 static int bus_setup_loop(Manager *m, DBusConnection *bus) {
718         assert(m);
719         assert(bus);
720
721         dbus_connection_set_exit_on_disconnect(bus, FALSE);
722
723         if (!dbus_connection_set_watch_functions(bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
724             !dbus_connection_set_timeout_functions(bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL))
725                 return log_oom();
726
727         if (set_put(m->bus_connections_for_dispatch, bus) < 0)
728                 return log_oom();
729
730         dbus_connection_set_dispatch_status_function(bus, bus_dispatch_status, m, NULL);
731         return 0;
732 }
733
734 static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) {
735         return uid == 0 || uid == geteuid();
736 }
737
738 static void bus_new_connection(
739                 DBusServer *server,
740                 DBusConnection *new_connection,
741                 void *data) {
742
743         Manager *m = data;
744
745         assert(m);
746
747         if (set_size(m->bus_connections) >= CONNECTIONS_MAX) {
748                 log_error("Too many concurrent connections.");
749                 return;
750         }
751
752         dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL);
753
754         if (bus_setup_loop(m, new_connection) < 0)
755                 return;
756
757         if (!dbus_connection_register_object_path(new_connection, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
758             !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
759             !dbus_connection_register_fallback(new_connection, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
760             !dbus_connection_add_filter(new_connection, private_bus_message_filter, m, NULL)) {
761                 log_oom();
762                 return;
763         }
764
765         log_debug("Accepted connection on private bus.");
766
767         dbus_connection_ref(new_connection);
768 }
769
770 static int init_registered_system_bus(Manager *m) {
771         char *id = NULL;
772
773         if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL))
774                 return log_oom();
775
776         if (m->running_as != SYSTEMD_SYSTEM) {
777                 DBusError error;
778
779                 dbus_error_init(&error);
780
781                 dbus_bus_add_match(m->system_bus,
782                                    "type='signal',"
783                                    "interface='org.freedesktop.systemd1.Agent',"
784                                    "member='Released',"
785                                    "path='/org/freedesktop/systemd1/agent'",
786                                    &error);
787
788                 if (dbus_error_is_set(&error)) {
789                         log_error("Failed to register match: %s", bus_error_message(&error));
790                         dbus_error_free(&error);
791                         return -1;
792                 }
793         }
794
795         log_debug("Successfully connected to system D-Bus bus %s as %s",
796                  strnull((id = dbus_connection_get_server_id(m->system_bus))),
797                  strnull(dbus_bus_get_unique_name(m->system_bus)));
798         dbus_free(id);
799
800         return 0;
801 }
802
803 static int init_registered_api_bus(Manager *m) {
804         int r;
805
806         if (!dbus_connection_register_object_path(m->api_bus, "/org/freedesktop/systemd1", &bus_manager_vtable, m) ||
807             !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/unit", &bus_unit_vtable, m) ||
808             !dbus_connection_register_fallback(m->api_bus, "/org/freedesktop/systemd1/job", &bus_job_vtable, m) ||
809             !dbus_connection_add_filter(m->api_bus, api_bus_message_filter, m, NULL))
810                 return log_oom();
811
812         /* Get NameOwnerChange messages */
813         dbus_bus_add_match(m->api_bus,
814                            "type='signal',"
815                            "sender='"DBUS_SERVICE_DBUS"',"
816                            "interface='"DBUS_INTERFACE_DBUS"',"
817                            "member='NameOwnerChanged',"
818                            "path='"DBUS_PATH_DBUS"'",
819                            NULL);
820
821         /* Get activation requests */
822         dbus_bus_add_match(m->api_bus,
823                            "type='signal',"
824                            "sender='"DBUS_SERVICE_DBUS"',"
825                            "interface='org.freedesktop.systemd1.Activator',"
826                            "member='ActivationRequest',"
827                            "path='"DBUS_PATH_DBUS"'",
828                            NULL);
829
830         r = request_name(m);
831         if (r < 0)
832                 return r;
833
834         r = query_name_list(m);
835         if (r < 0)
836                 return r;
837
838         if (m->running_as == SYSTEMD_USER) {
839                 char *id = NULL;
840
841                 log_debug("Successfully connected to API D-Bus bus %s as %s",
842                          strnull((id = dbus_connection_get_server_id(m->api_bus))),
843                          strnull(dbus_bus_get_unique_name(m->api_bus)));
844                 dbus_free(id);
845         } else
846                 log_debug("Successfully initialized API on the system bus");
847
848         return 0;
849 }
850
851 static void bus_register_cb(DBusPendingCall *pending, void *userdata) {
852         Manager *m = userdata;
853         DBusConnection **conn;
854         DBusMessage *reply;
855         DBusError error;
856         const char *name;
857         int r = 0;
858
859         dbus_error_init(&error);
860
861         conn = dbus_pending_call_get_data(pending, m->conn_data_slot);
862         assert(conn == &m->system_bus || conn == &m->api_bus);
863
864         reply = dbus_pending_call_steal_reply(pending);
865
866         switch (dbus_message_get_type(reply)) {
867         case DBUS_MESSAGE_TYPE_ERROR:
868                 assert_se(dbus_set_error_from_message(&error, reply));
869                 log_warning("Failed to register to bus: %s", bus_error_message(&error));
870                 r = -1;
871                 break;
872         case DBUS_MESSAGE_TYPE_METHOD_RETURN:
873                 if (!dbus_message_get_args(reply, &error,
874                                            DBUS_TYPE_STRING, &name,
875                                            DBUS_TYPE_INVALID)) {
876                         log_error("Failed to parse Hello reply: %s", bus_error_message(&error));
877                         r = -1;
878                         break;
879                 }
880
881                 log_debug("Received name %s in reply to Hello", name);
882                 if (!dbus_bus_set_unique_name(*conn, name)) {
883                         log_error("Failed to set unique name");
884                         r = -1;
885                         break;
886                 }
887
888                 if (conn == &m->system_bus) {
889                         r = init_registered_system_bus(m);
890                         if (r == 0 && m->running_as == SYSTEMD_SYSTEM)
891                                 r = init_registered_api_bus(m);
892                 } else
893                         r = init_registered_api_bus(m);
894
895                 break;
896         default:
897                 assert_not_reached("Invalid reply message");
898         }
899
900         dbus_message_unref(reply);
901         dbus_error_free(&error);
902
903         if (r < 0) {
904                 if (conn == &m->system_bus) {
905                         log_debug("Failed setting up the system bus");
906                         bus_done_system(m);
907                 } else {
908                         log_debug("Failed setting up the API bus");
909                         bus_done_api(m);
910                 }
911         }
912 }
913
914 static int manager_bus_async_register(Manager *m, DBusConnection **conn) {
915         DBusMessage *message = NULL;
916         DBusPendingCall *pending = NULL;
917
918         message = dbus_message_new_method_call(DBUS_SERVICE_DBUS,
919                                                DBUS_PATH_DBUS,
920                                                DBUS_INTERFACE_DBUS,
921                                                "Hello");
922         if (!message)
923                 goto oom;
924
925         if (!dbus_connection_send_with_reply(*conn, message, &pending, -1))
926                 goto oom;
927
928         if (!dbus_pending_call_set_data(pending, m->conn_data_slot, conn, NULL))
929                 goto oom;
930
931         if (!dbus_pending_call_set_notify(pending, bus_register_cb, m, NULL))
932                 goto oom;
933
934         dbus_message_unref(message);
935         dbus_pending_call_unref(pending);
936
937         return 0;
938 oom:
939         if (pending) {
940                 dbus_pending_call_cancel(pending);
941                 dbus_pending_call_unref(pending);
942         }
943
944         if (message)
945                 dbus_message_unref(message);
946
947         return -ENOMEM;
948 }
949
950 static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) {
951         const char *address;
952         DBusConnection *connection;
953         DBusError error;
954
955         switch (type) {
956         case DBUS_BUS_SYSTEM:
957                 address = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
958                 if (!address || !address[0])
959                         address = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS;
960                 break;
961         case DBUS_BUS_SESSION:
962                 address = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
963                 if (!address || !address[0])
964                         address = DBUS_SESSION_BUS_DEFAULT_ADDRESS;
965                 break;
966         default:
967                 assert_not_reached("Invalid bus type");
968         }
969
970         dbus_error_init(&error);
971
972         connection = dbus_connection_open_private(address, &error);
973         if (!connection) {
974                 log_warning("Failed to open private bus connection: %s", bus_error_message(&error));
975                 goto fail;
976         }
977
978         return connection;
979
980 fail:
981         dbus_error_free(&error);
982         return NULL;
983 }
984
985 static int bus_init_system(Manager *m) {
986         int r;
987
988         if (m->system_bus)
989                 return 0;
990
991         m->system_bus = manager_bus_connect_private(m, DBUS_BUS_SYSTEM);
992         if (!m->system_bus) {
993                 log_debug("Failed to connect to system D-Bus, retrying later");
994                 r = 0;
995                 goto fail;
996         }
997
998         r = bus_setup_loop(m, m->system_bus);
999         if (r < 0)
1000                 goto fail;
1001
1002         r = manager_bus_async_register(m, &m->system_bus);
1003         if (r < 0)
1004                 goto fail;
1005
1006         return 0;
1007 fail:
1008         bus_done_system(m);
1009
1010         return r;
1011 }
1012
1013 static int bus_init_api(Manager *m) {
1014         int r;
1015
1016         if (m->api_bus)
1017                 return 0;
1018
1019         if (m->running_as == SYSTEMD_SYSTEM) {
1020                 m->api_bus = m->system_bus;
1021                 /* In this mode there is no distinct connection to the API bus,
1022                  * the API is published on the system bus.
1023                  * bus_register_cb() is aware of that and will init the API
1024                  * when the system bus gets registered.
1025                  * No need to setup anything here. */
1026                 return 0;
1027         }
1028
1029         m->api_bus = manager_bus_connect_private(m, DBUS_BUS_SESSION);
1030         if (!m->api_bus) {
1031                 log_debug("Failed to connect to API D-Bus, retrying later");
1032                 r = 0;
1033                 goto fail;
1034         }
1035
1036         r = bus_setup_loop(m, m->api_bus);
1037         if (r < 0)
1038                 goto fail;
1039
1040         r = manager_bus_async_register(m, &m->api_bus);
1041         if (r < 0)
1042                 goto fail;
1043
1044         return 0;
1045 fail:
1046         bus_done_api(m);
1047
1048         return r;
1049 }
1050
1051 static int bus_init_private(Manager *m) {
1052         DBusError error;
1053         int r;
1054         static const char *const external_only[] = {
1055                 "EXTERNAL",
1056                 NULL
1057         };
1058
1059         assert(m);
1060
1061         dbus_error_init(&error);
1062
1063         if (m->private_bus)
1064                 return 0;
1065
1066         if (m->running_as == SYSTEMD_SYSTEM) {
1067
1068                 /* We want the private bus only when running as init */
1069                 if (getpid() != 1)
1070                         return 0;
1071
1072                 unlink("/run/systemd/private");
1073                 m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error);
1074         } else {
1075                 const char *e;
1076                 char *p;
1077                 char *escaped;
1078
1079                 e = secure_getenv("XDG_RUNTIME_DIR");
1080                 if (!e)
1081                         return 0;
1082
1083                 if (asprintf(&p, "%s/systemd/private", e) < 0) {
1084                         r = log_oom();
1085                         goto fail;
1086                 }
1087
1088                 mkdir_parents_label(p, 0755);
1089                 unlink(p);
1090                 free(p);
1091
1092                 escaped = dbus_address_escape_value(e);
1093                 if (!escaped) {
1094                         r = log_oom();
1095                         goto fail;
1096                 }
1097                 if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) {
1098                         dbus_free(escaped);
1099                         r = log_oom();
1100                         goto fail;
1101                 }
1102                 dbus_free(escaped);
1103
1104                 m->private_bus = dbus_server_listen(p, &error);
1105                 free(p);
1106         }
1107
1108         if (!m->private_bus) {
1109                 log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
1110                 r = -EIO;
1111                 goto fail;
1112         }
1113
1114         if (!dbus_server_set_auth_mechanisms(m->private_bus, (const char**) external_only) ||
1115             !dbus_server_set_watch_functions(m->private_bus, bus_add_watch, bus_remove_watch, bus_toggle_watch, m, NULL) ||
1116             !dbus_server_set_timeout_functions(m->private_bus, bus_add_timeout, bus_remove_timeout, bus_toggle_timeout, m, NULL)) {
1117                 r = log_oom();
1118                 goto fail;
1119         }
1120
1121         dbus_server_set_new_connection_function(m->private_bus, bus_new_connection, m, NULL);
1122
1123         log_debug("Successfully created private D-Bus server.");
1124
1125         return 0;
1126
1127 fail:
1128         bus_done_private(m);
1129         dbus_error_free(&error);
1130
1131         return r;
1132 }
1133
1134 int bus_init(Manager *m, bool try_bus_connect) {
1135         int r;
1136
1137         if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 ||
1138             set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0)
1139                 return log_oom();
1140
1141         if (m->name_data_slot < 0)
1142                 if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot))
1143                         return log_oom();
1144
1145         if (m->conn_data_slot < 0)
1146                 if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot))
1147                         return log_oom();
1148
1149         if (m->subscribed_data_slot < 0)
1150                 if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot))
1151                         return log_oom();
1152
1153         if (try_bus_connect) {
1154                 if ((r = bus_init_system(m)) < 0 ||
1155                     (r = bus_init_api(m)) < 0)
1156                         return r;
1157         }
1158
1159         r = bus_init_private(m);
1160         if (r < 0)
1161                 return r;
1162
1163         return 0;
1164 }
1165
1166 static void shutdown_connection(Manager *m, DBusConnection *c) {
1167         Job *j;
1168         Iterator i;
1169
1170         HASHMAP_FOREACH(j, m->jobs, i) {
1171                 JobBusClient *cl, *nextcl;
1172                 LIST_FOREACH_SAFE(client, cl, nextcl, j->bus_client_list) {
1173                         if (cl->bus == c) {
1174                                 LIST_REMOVE(client, j->bus_client_list, cl);
1175                                 free(cl);
1176                         }
1177                 }
1178         }
1179
1180         set_remove(m->bus_connections, c);
1181         set_remove(m->bus_connections_for_dispatch, c);
1182         set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c));
1183
1184         if (m->queued_message_connection == c) {
1185                 m->queued_message_connection = NULL;
1186
1187                 if (m->queued_message) {
1188                         dbus_message_unref(m->queued_message);
1189                         m->queued_message = NULL;
1190                 }
1191         }
1192
1193         dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL);
1194         /* system manager cannot afford to block on DBus */
1195         if (m->running_as != SYSTEMD_SYSTEM)
1196                 dbus_connection_flush(c);
1197         dbus_connection_close(c);
1198         dbus_connection_unref(c);
1199 }
1200
1201 static void bus_done_api(Manager *m) {
1202         if (!m->api_bus)
1203                 return;
1204
1205         if (m->running_as == SYSTEMD_USER)
1206                 shutdown_connection(m, m->api_bus);
1207
1208         m->api_bus = NULL;
1209
1210         if (m->queued_message) {
1211                 dbus_message_unref(m->queued_message);
1212                 m->queued_message = NULL;
1213         }
1214 }
1215
1216 static void bus_done_system(Manager *m) {
1217         if (!m->system_bus)
1218                 return;
1219
1220         if (m->running_as == SYSTEMD_SYSTEM)
1221                 bus_done_api(m);
1222
1223         shutdown_connection(m, m->system_bus);
1224         m->system_bus = NULL;
1225 }
1226
1227 static void bus_done_private(Manager *m) {
1228         if (!m->private_bus)
1229                 return;
1230
1231         dbus_server_disconnect(m->private_bus);
1232         dbus_server_unref(m->private_bus);
1233         m->private_bus = NULL;
1234 }
1235
1236 void bus_done(Manager *m) {
1237         DBusConnection *c;
1238
1239         bus_done_api(m);
1240         bus_done_system(m);
1241         bus_done_private(m);
1242
1243         while ((c = set_steal_first(m->bus_connections)))
1244                 shutdown_connection(m, c);
1245
1246         while ((c = set_steal_first(m->bus_connections_for_dispatch)))
1247                 shutdown_connection(m, c);
1248
1249         set_free(m->bus_connections);
1250         set_free(m->bus_connections_for_dispatch);
1251
1252         if (m->name_data_slot >= 0)
1253                 dbus_pending_call_free_data_slot(&m->name_data_slot);
1254
1255         if (m->conn_data_slot >= 0)
1256                 dbus_pending_call_free_data_slot(&m->conn_data_slot);
1257
1258         if (m->subscribed_data_slot >= 0)
1259                 dbus_connection_free_data_slot(&m->subscribed_data_slot);
1260 }
1261
1262 static void query_pid_pending_cb(DBusPendingCall *pending, void *userdata) {
1263         Manager *m = userdata;
1264         DBusMessage *reply;
1265         DBusError error;
1266         const char *name;
1267
1268         dbus_error_init(&error);
1269
1270         assert_se(name = BUS_PENDING_CALL_NAME(m, pending));
1271         assert_se(reply = dbus_pending_call_steal_reply(pending));
1272
1273         switch (dbus_message_get_type(reply)) {
1274
1275         case DBUS_MESSAGE_TYPE_ERROR:
1276
1277                 assert_se(dbus_set_error_from_message(&error, reply));
1278                 log_warning("GetConnectionUnixProcessID() failed: %s", bus_error_message(&error));
1279                 break;
1280
1281         case DBUS_MESSAGE_TYPE_METHOD_RETURN: {
1282                 uint32_t r;
1283
1284                 if (!dbus_message_get_args(reply,
1285                                            &error,
1286                                            DBUS_TYPE_UINT32, &r,
1287                                            DBUS_TYPE_INVALID)) {
1288                         log_error("Failed to parse GetConnectionUnixProcessID() reply: %s", bus_error_message(&error));
1289                         break;
1290                 }
1291
1292                 manager_dispatch_bus_query_pid_done(m, name, (pid_t) r);
1293                 break;
1294         }
1295
1296         default:
1297                 assert_not_reached("Invalid reply message");
1298         }
1299
1300         dbus_message_unref(reply);
1301         dbus_error_free(&error);
1302 }
1303
1304 int bus_query_pid(Manager *m, const char *name) {
1305         DBusMessage *message = NULL;
1306         DBusPendingCall *pending = NULL;
1307         char *n = NULL;
1308
1309         assert(m);
1310         assert(name);
1311
1312         if (!(message = dbus_message_new_method_call(
1313                               DBUS_SERVICE_DBUS,
1314                               DBUS_PATH_DBUS,
1315                               DBUS_INTERFACE_DBUS,
1316                               "GetConnectionUnixProcessID")))
1317                 goto oom;
1318
1319         if (!(dbus_message_append_args(
1320                               message,
1321                               DBUS_TYPE_STRING, &name,
1322                               DBUS_TYPE_INVALID)))
1323                 goto oom;
1324
1325         if (!dbus_connection_send_with_reply(m->api_bus, message, &pending, -1))
1326                 goto oom;
1327
1328         if (!(n = strdup(name)))
1329                 goto oom;
1330
1331         if (!dbus_pending_call_set_data(pending, m->name_data_slot, n, free))
1332                 goto oom;
1333
1334         n = NULL;
1335
1336         if (!dbus_pending_call_set_notify(pending, query_pid_pending_cb, m, NULL))
1337                 goto oom;
1338
1339         dbus_message_unref(message);
1340         dbus_pending_call_unref(pending);
1341
1342         return 0;
1343
1344 oom:
1345         free(n);
1346
1347         if (pending) {
1348                 dbus_pending_call_cancel(pending);
1349                 dbus_pending_call_unref(pending);
1350         }
1351
1352         if (message)
1353                 dbus_message_unref(message);
1354
1355         return -ENOMEM;
1356 }
1357
1358 int bus_broadcast(Manager *m, DBusMessage *message) {
1359         bool oom = false;
1360         Iterator i;
1361         DBusConnection *c;
1362
1363         assert(m);
1364         assert(message);
1365
1366         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1367                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1368                         oom = !dbus_connection_send(c, message, NULL);
1369
1370         SET_FOREACH(c, m->bus_connections, i)
1371                 if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM)
1372                         oom = !dbus_connection_send(c, message, NULL);
1373
1374         return oom ? -ENOMEM : 0;
1375 }
1376
1377 bool bus_has_subscriber(Manager *m) {
1378         Iterator i;
1379         DBusConnection *c;
1380
1381         assert(m);
1382
1383         /* If we are reloading then we might not have deserialized the
1384            subscribers yet, hence let's assume that there are some */
1385
1386         if (m->n_reloading > 0)
1387                 return true;
1388
1389         SET_FOREACH(c, m->bus_connections_for_dispatch, i)
1390                 if (bus_connection_has_subscriber(m, c))
1391                         return true;
1392
1393         SET_FOREACH(c, m->bus_connections, i)
1394                 if (bus_connection_has_subscriber(m, c))
1395                         return true;
1396
1397         return false;
1398 }
1399
1400 bool bus_connection_has_subscriber(Manager *m, DBusConnection *c) {
1401         assert(m);
1402         assert(c);
1403
1404         return !set_isempty(BUS_CONNECTION_SUBSCRIBED(m, c));
1405 }
1406
1407 int bus_fdset_add_all(Manager *m, FDSet *fds) {
1408         Iterator i;
1409         DBusConnection *c;
1410
1411         assert(m);
1412         assert(fds);
1413
1414         /* When we are about to reexecute we add all D-Bus fds to the
1415          * set to pass over to the newly executed systemd. They won't
1416          * be used there however, except that they are closed at the
1417          * very end of deserialization, those making it possible for
1418          * clients to synchronously wait for systemd to reexec by
1419          * simply waiting for disconnection */
1420
1421         SET_FOREACH(c, m->bus_connections_for_dispatch, i) {
1422                 int fd;
1423
1424                 if (dbus_connection_get_unix_fd(c, &fd)) {
1425                         fd = fdset_put_dup(fds, fd);
1426
1427                         if (fd < 0)
1428                                 return fd;
1429                 }
1430         }
1431
1432         SET_FOREACH(c, m->bus_connections, i) {
1433                 int fd;
1434
1435                 if (dbus_connection_get_unix_fd(c, &fd)) {
1436                         fd = fdset_put_dup(fds, fd);
1437
1438                         if (fd < 0)
1439                                 return fd;
1440                 }
1441         }
1442
1443         return 0;
1444 }
1445
1446 void bus_broadcast_finished(
1447                 Manager *m,
1448                 usec_t firmware_usec,
1449                 usec_t loader_usec,
1450                 usec_t kernel_usec,
1451                 usec_t initrd_usec,
1452                 usec_t userspace_usec,
1453                 usec_t total_usec) {
1454
1455         _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1456
1457         assert(m);
1458
1459         message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartupFinished");
1460         if (!message) {
1461                 log_oom();
1462                 return;
1463         }
1464
1465         assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1466         if (!dbus_message_append_args(message,
1467                                       DBUS_TYPE_UINT64, &firmware_usec,
1468                                       DBUS_TYPE_UINT64, &loader_usec,
1469                                       DBUS_TYPE_UINT64, &kernel_usec,
1470                                       DBUS_TYPE_UINT64, &initrd_usec,
1471                                       DBUS_TYPE_UINT64, &userspace_usec,
1472                                       DBUS_TYPE_UINT64, &total_usec,
1473                                       DBUS_TYPE_INVALID)) {
1474                 log_oom();
1475                 return;
1476         }
1477
1478
1479         if (bus_broadcast(m, message) < 0) {
1480                 log_oom();
1481                 return;
1482         }
1483 }
1484
1485 void bus_broadcast_reloading(Manager *m, bool active) {
1486
1487         _cleanup_dbus_message_unref_ DBusMessage *message = NULL;
1488         dbus_bool_t b = active;
1489
1490         assert(m);
1491
1492         message = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "Reloading");
1493         if (!message) {
1494                 log_oom();
1495                 return;
1496         }
1497
1498         assert_cc(sizeof(usec_t) == sizeof(uint64_t));
1499         if (!dbus_message_append_args(message,
1500                                       DBUS_TYPE_BOOLEAN, &b,
1501                                       DBUS_TYPE_INVALID)) {
1502                 log_oom();
1503                 return;
1504         }
1505
1506
1507         if (bus_broadcast(m, message) < 0) {
1508                 log_oom();
1509                 return;
1510         }
1511 }
1512
1513 Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) {
1514         Set *s;
1515
1516         assert(m);
1517         assert(c);
1518
1519         s = BUS_CONNECTION_SUBSCRIBED(m, c);
1520         if (s)
1521                 return s;
1522
1523         s = set_new(string_hash_func, string_compare_func);
1524         if (!s)
1525                 return NULL;
1526
1527         if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) {
1528                 set_free(s);
1529                 return NULL;
1530         }
1531
1532         return s;
1533 }
1534
1535 void bus_serialize(Manager *m, FILE *f) {
1536         char *client;
1537         Iterator i;
1538         Set *s;
1539
1540         assert(m);
1541         assert(f);
1542
1543         if (!m->api_bus)
1544                 return;
1545
1546         s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus);
1547         SET_FOREACH(client, s, i)
1548                 fprintf(f, "subscribed=%s\n", client);
1549 }
1550
1551 int bus_deserialize_item(Manager *m, const char *line) {
1552         const char *e;
1553         char *b;
1554         Set *s;
1555
1556         assert(m);
1557         assert(line);
1558
1559         if (!m->api_bus)
1560                 return 0;
1561
1562         e = startswith(line, "subscribed=");
1563         if (!e)
1564                 return 0;
1565
1566         s = bus_acquire_subscribed(m, m->api_bus);
1567         if (!s)
1568                 return -ENOMEM;
1569
1570         b = strdup(e);
1571         if (!b)
1572                 return -ENOMEM;
1573
1574         set_consume(s, b);
1575
1576         return 1;
1577 }