1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
23 #include <sys/socket.h>
28 #include <dbus/dbus.h>
30 #include <sys/epoll.h>
33 #include "dbus-common.h"
38 int bus_check_peercred(DBusConnection *c) {
45 assert_se(dbus_connection_get_unix_fd(c, &fd));
47 l = sizeof(struct ucred);
48 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
49 log_error("SO_PEERCRED failed: %m");
53 if (l != sizeof(struct ucred)) {
54 log_error("SO_PEERCRED returned wrong size.");
58 if (ucred.uid != 0 && ucred.uid != geteuid())
64 static int sync_auth(DBusConnection *bus, DBusError *error) {
69 /* This complexity should probably move into D-Bus itself:
71 * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
73 begin = tstamp = now(CLOCK_MONOTONIC);
76 if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
79 if (dbus_connection_get_is_authenticated(bus))
82 if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
85 tstamp = now(CLOCK_MONOTONIC);
88 if (!dbus_connection_get_is_connected(bus)) {
89 dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
93 if (!dbus_connection_get_is_authenticated(bus)) {
94 dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
101 int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) {
102 DBusConnection *bus = NULL;
108 if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
109 /* If we are root, then let's talk directly to the
110 * system instance, instead of going via the bus */
112 bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
117 if (t == DBUS_BUS_SESSION) {
120 /* If we are supposed to talk to the instance,
121 * try via XDG_RUNTIME_DIR first, then
122 * fallback to normal bus access */
124 e = getenv("XDG_RUNTIME_DIR");
128 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
131 bus = dbus_connection_open_private(p, NULL);
137 bus = dbus_bus_get_private(t, error);
145 dbus_connection_set_exit_on_disconnect(bus, FALSE);
148 if (bus_check_peercred(bus) < 0) {
149 dbus_connection_close(bus);
150 dbus_connection_unref(bus);
152 dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
157 r = sync_auth(bus, error);
159 dbus_connection_close(bus);
160 dbus_connection_unref(bus);
171 int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
177 assert(user || host);
180 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@%s,argv3=systemd-stdio-bridge", user, host);
182 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s@localhost,argv3=systemd-stdio-bridge", user);
184 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
187 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
191 bus = dbus_connection_open_private(p, error);
197 dbus_connection_set_exit_on_disconnect(bus, FALSE);
199 if ((r = sync_auth(bus, error)) < 0) {
200 dbus_connection_close(bus);
201 dbus_connection_unref(bus);
205 if (!dbus_bus_register(bus, error)) {
206 dbus_connection_close(bus);
207 dbus_connection_unref(bus);
215 int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
221 /* Don't bother with PolicyKit if we are root */
223 return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
225 bus = dbus_connection_open_private("unixexec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error);
229 dbus_connection_set_exit_on_disconnect(bus, FALSE);
231 if ((r = sync_auth(bus, error)) < 0) {
232 dbus_connection_close(bus);
233 dbus_connection_unref(bus);
237 if (!dbus_bus_register(bus, error)) {
238 dbus_connection_close(bus);
239 dbus_connection_unref(bus);
247 const char *bus_error_message(const DBusError *error) {
250 /* Sometimes the D-Bus server is a little bit too verbose with
251 * its error messages, so let's override them here */
252 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
253 return "Access denied";
255 return error->message;
258 DBusHandlerResult bus_default_message_handler(
260 DBusMessage *message,
261 const char *introspection,
262 const char *interfaces,
263 const BusBoundProperties *bound_properties) {
266 DBusMessage *reply = NULL;
272 dbus_error_init(&error);
274 if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
276 if (!(reply = dbus_message_new_method_return(message)))
279 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
282 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
283 const char *interface, *property;
284 const BusBoundProperties *bp;
285 const BusProperty *p;
287 DBusMessageIter iter, sub;
289 if (!dbus_message_get_args(
292 DBUS_TYPE_STRING, &interface,
293 DBUS_TYPE_STRING, &property,
295 return bus_send_error_reply(c, message, &error, -EINVAL);
297 for (bp = bound_properties; bp->interface; bp++) {
298 if (!streq(bp->interface, interface))
301 for (p = bp->properties; p->property; p++)
302 if (streq(p->property, property))
307 if (!nulstr_contains(interfaces, interface))
308 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
310 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
312 return bus_send_error_reply(c, message, &error, -EINVAL);
315 reply = dbus_message_new_method_return(message);
319 dbus_message_iter_init_append(reply, &iter);
321 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
324 data = (char*)bp->base + p->offset;
326 data = *(void**)data;
327 r = p->append(&sub, property, data);
332 dbus_message_unref(reply);
333 return bus_send_error_reply(c, message, NULL, r);
336 if (!dbus_message_iter_close_container(&iter, &sub))
339 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) {
340 const char *interface;
341 const BusBoundProperties *bp;
342 const BusProperty *p;
343 DBusMessageIter iter, sub, sub2, sub3;
345 if (!dbus_message_get_args(
348 DBUS_TYPE_STRING, &interface,
350 return bus_send_error_reply(c, message, &error, -EINVAL);
352 if (interface[0] && !nulstr_contains(interfaces, interface)) {
353 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
354 return bus_send_error_reply(c, message, &error, -EINVAL);
357 if (!(reply = dbus_message_new_method_return(message)))
360 dbus_message_iter_init_append(reply, &iter);
362 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
365 for (bp = bound_properties; bp->interface; bp++) {
366 if (interface[0] && !streq(bp->interface, interface))
369 for (p = bp->properties; p->property; p++) {
372 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
373 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
374 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
377 data = (char*)bp->base + p->offset;
379 data = *(void**)data;
380 r = p->append(&sub3, p->property, data);
385 dbus_message_unref(reply);
386 return bus_send_error_reply(c, message, NULL, r);
389 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
390 !dbus_message_iter_close_container(&sub, &sub2))
395 if (!dbus_message_iter_close_container(&iter, &sub))
398 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
399 const char *interface, *property;
400 DBusMessageIter iter;
401 const BusBoundProperties *bp;
402 const BusProperty *p;
406 DBusMessage *changed;
408 if (!dbus_message_iter_init(message, &iter) ||
409 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
410 return bus_send_error_reply(c, message, NULL, -EINVAL);
412 dbus_message_iter_get_basic(&iter, &interface);
414 if (!dbus_message_iter_next(&iter) ||
415 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
416 return bus_send_error_reply(c, message, NULL, -EINVAL);
418 dbus_message_iter_get_basic(&iter, &property);
420 if (!dbus_message_iter_next(&iter) ||
421 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
422 dbus_message_iter_has_next(&iter))
423 return bus_send_error_reply(c, message, NULL, -EINVAL);
425 for (bp = bound_properties; bp->interface; bp++) {
426 if (!streq(bp->interface, interface))
429 for (p = bp->properties; p->property; p++)
430 if (streq(p->property, property))
435 if (!nulstr_contains(interfaces, interface))
436 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
438 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
440 return bus_send_error_reply(c, message, &error, -EINVAL);
444 dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
445 return bus_send_error_reply(c, message, &error, -EINVAL);
448 dbus_message_iter_recurse(&iter, &sub);
450 sig = dbus_message_iter_get_signature(&sub);
454 if (!streq(sig, p->signature)) {
456 return bus_send_error_reply(c, message, NULL, -EINVAL);
460 data = (uint8_t*) bp->base + p->offset;
462 data = *(void**)data;
464 r = p->set(&sub, property, data);
468 return bus_send_error_reply(c, message, NULL, r);
470 reply = dbus_message_new_method_return(message);
474 /* Send out a signal about this, but it doesn't really
475 * matter if this fails, so eat all errors */
476 changed = bus_properties_changed_one_new(
477 dbus_message_get_path(message),
481 dbus_connection_send(c, changed, NULL);
482 dbus_message_unref(changed);
487 const char *interface = dbus_message_get_interface(message);
489 if (!interface || !nulstr_contains(interfaces, interface)) {
490 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
491 return bus_send_error_reply(c, message, &error, -EINVAL);
496 if (!dbus_connection_send(c, reply, NULL))
499 dbus_message_unref(reply);
500 return DBUS_HANDLER_RESULT_HANDLED;
503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
507 dbus_message_unref(reply);
509 dbus_error_free(&error);
511 return DBUS_HANDLER_RESULT_NEED_MEMORY;
514 int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
515 const char *t = data;
523 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
529 int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
535 return bus_append_strv_iter(i, t);
538 int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
548 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
554 int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
564 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
570 int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
575 /* Let's ensure that usec_t is actually 64bit, and hence this
576 * function can be used for usec_t */
577 assert_cc(sizeof(uint64_t) == sizeof(usec_t));
579 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
585 int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
590 /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
591 * 32bit, and hence this function can be used for
592 * pid_t/mode_t/uid_t/gid_t */
593 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
594 assert_cc(sizeof(uint32_t) == sizeof(mode_t));
595 assert_cc(sizeof(uint32_t) == sizeof(unsigned));
596 assert_cc(sizeof(uint32_t) == sizeof(uid_t));
597 assert_cc(sizeof(uint32_t) == sizeof(gid_t));
599 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
605 int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
610 assert_cc(sizeof(int32_t) == sizeof(int));
612 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
618 int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
625 u = (uint64_t) *(size_t*) data;
627 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
633 int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
640 u = (uint64_t) *(unsigned long*) data;
642 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
648 int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
655 l = (int64_t) *(long*) data;
657 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
663 int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
669 dbus_message_iter_get_basic(i, t);
673 const char *bus_errno_to_dbus(int error) {
678 return DBUS_ERROR_INVALID_ARGS;
681 return DBUS_ERROR_NO_MEMORY;
685 return DBUS_ERROR_ACCESS_DENIED;
688 return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
691 return DBUS_ERROR_FILE_NOT_FOUND;
694 return DBUS_ERROR_FILE_EXISTS;
698 return DBUS_ERROR_TIMEOUT;
701 return DBUS_ERROR_IO_ERROR;
706 return DBUS_ERROR_DISCONNECTED;
709 return DBUS_ERROR_FAILED;
712 DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
713 DBusMessage *reply = NULL;
714 const char *name, *text;
716 if (berror && dbus_error_is_set(berror)) {
718 text = berror->message;
720 name = bus_errno_to_dbus(error);
721 text = strerror(-error);
724 if (!(reply = dbus_message_new_error(message, name, text)))
727 if (!dbus_connection_send(c, reply, NULL))
730 dbus_message_unref(reply);
733 dbus_error_free(berror);
735 return DBUS_HANDLER_RESULT_HANDLED;
739 dbus_message_unref(reply);
742 dbus_error_free(berror);
744 return DBUS_HANDLER_RESULT_NEED_MEMORY;
747 DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
749 DBusMessageIter iter, sub;
755 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
759 dbus_message_iter_init_append(m, &iter);
761 /* We won't send any property values, since they might be
762 * large and sometimes not cheap to generated */
764 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
765 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
766 !dbus_message_iter_close_container(&iter, &sub) ||
767 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
770 NULSTR_FOREACH(i, properties)
771 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
774 if (!dbus_message_iter_close_container(&iter, &sub))
781 dbus_message_unref(m);
786 DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
788 DBusMessageIter iter, sub;
793 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
797 dbus_message_iter_init_append(m, &iter);
799 /* We won't send any property values, since they might be
800 * large and sometimes not cheap to generated */
802 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
803 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
804 !dbus_message_iter_close_container(&iter, &sub) ||
805 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
808 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
811 if (!dbus_message_iter_close_container(&iter, &sub))
818 dbus_message_unref(m);
823 uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
829 /* no watch flags for disabled watches */
830 if (!dbus_watch_get_enabled(bus_watch))
833 flags = dbus_watch_get_flags(bus_watch);
835 if (flags & DBUS_WATCH_READABLE)
837 if (flags & DBUS_WATCH_WRITABLE)
840 return events | EPOLLHUP | EPOLLERR;
843 unsigned bus_events_to_flags(uint32_t events) {
846 if (events & EPOLLIN)
847 flags |= DBUS_WATCH_READABLE;
848 if (events & EPOLLOUT)
849 flags |= DBUS_WATCH_WRITABLE;
850 if (events & EPOLLHUP)
851 flags |= DBUS_WATCH_HANGUP;
852 if (events & EPOLLERR)
853 flags |= DBUS_WATCH_ERROR;
858 int bus_parse_strv(DBusMessage *m, char ***_l) {
859 DBusMessageIter iter;
864 if (!dbus_message_iter_init(m, &iter))
867 return bus_parse_strv_iter(&iter, _l);
870 int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
872 unsigned n = 0, i = 0;
878 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
879 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
882 dbus_message_iter_recurse(iter, &sub);
884 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
886 dbus_message_iter_next(&sub);
889 if (!(l = new(char*, n+1)))
892 dbus_message_iter_recurse(iter, &sub);
894 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
897 assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
898 dbus_message_iter_get_basic(&sub, &s);
900 if (!(l[i++] = strdup(s))) {
905 dbus_message_iter_next(&sub);
917 int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
922 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
926 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
929 if (!dbus_message_iter_close_container(iter, &sub))
935 int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
940 if (dbus_message_iter_get_arg_type(iter) != type)
943 dbus_message_iter_get_basic(iter, data);
945 if (!dbus_message_iter_next(iter) != !next)
951 int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
955 switch (dbus_message_iter_get_arg_type(iter)) {
957 case DBUS_TYPE_STRING: {
959 dbus_message_iter_get_basic(iter, &s);
961 if (all || !isempty(s))
962 printf("%s=%s\n", name, s);
967 case DBUS_TYPE_BOOLEAN: {
970 dbus_message_iter_get_basic(iter, &b);
971 printf("%s=%s\n", name, yes_no(b));
976 case DBUS_TYPE_UINT64: {
978 dbus_message_iter_get_basic(iter, &u);
980 /* Yes, heuristics! But we can change this check
981 * should it turn out to not be sufficient */
983 if (endswith(name, "Timestamp")) {
984 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
986 t = format_timestamp(timestamp, sizeof(timestamp), u);
988 printf("%s=%s\n", name, strempty(t));
990 } else if (strstr(name, "USec")) {
991 char timespan[FORMAT_TIMESPAN_MAX];
993 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u));
995 printf("%s=%llu\n", name, (unsigned long long) u);
1000 case DBUS_TYPE_UINT32: {
1002 dbus_message_iter_get_basic(iter, &u);
1004 if (strstr(name, "UMask") || strstr(name, "Mode"))
1005 printf("%s=%04o\n", name, u);
1007 printf("%s=%u\n", name, (unsigned) u);
1012 case DBUS_TYPE_INT32: {
1014 dbus_message_iter_get_basic(iter, &i);
1016 printf("%s=%i\n", name, (int) i);
1020 case DBUS_TYPE_DOUBLE: {
1022 dbus_message_iter_get_basic(iter, &d);
1024 printf("%s=%g\n", name, d);
1028 case DBUS_TYPE_ARRAY:
1030 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
1031 DBusMessageIter sub;
1034 dbus_message_iter_recurse(iter, &sub);
1036 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1037 printf("%s=", name);
1039 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1042 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
1043 dbus_message_iter_get_basic(&sub, &s);
1044 printf("%s%s", space ? " " : "", s);
1047 dbus_message_iter_next(&sub);
1055 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
1056 DBusMessageIter sub;
1058 dbus_message_iter_recurse(iter, &sub);
1060 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1061 printf("%s=", name);
1063 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1066 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
1067 dbus_message_iter_get_basic(&sub, &u);
1070 dbus_message_iter_next(&sub);
1085 static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
1087 DBusConnection *bus = userdata;
1089 assert_se(reply = dbus_pending_call_steal_reply(pending));
1090 dbus_message_unref(reply);
1092 dbus_connection_close(bus);
1095 void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
1096 DBusMessage *m = NULL;
1097 DBusPendingCall *pending = NULL;
1101 /* We unregister the name here, but we continue to process
1102 * requests, until we get the response for it, so that all
1103 * requests are guaranteed to be processed. */
1105 m = dbus_message_new_method_call(
1108 DBUS_INTERFACE_DBUS,
1113 if (!dbus_message_append_args(
1120 if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
1123 if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
1126 dbus_message_unref(m);
1127 dbus_pending_call_unref(pending);
1132 log_error("Out of memory");
1135 dbus_pending_call_cancel(pending);
1136 dbus_pending_call_unref(pending);
1140 dbus_message_unref(m);
1143 DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
1144 usec_t *remain_until = userdata;
1148 assert(remain_until);
1150 /* Everytime we get a new message we reset out timeout */
1151 *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
1153 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
1154 dbus_connection_close(bus);
1156 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;