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) {
251 /* Sometimes the D-Bus server is a little bit too verbose with
252 * its error messages, so let's override them here */
253 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
254 return "Access denied";
256 return error->message;
259 const char *bus_error_message_or_strerror(const DBusError *error, int err) {
261 if (error && dbus_error_is_set(error))
262 return bus_error_message(error);
264 return strerror(err);
267 DBusHandlerResult bus_default_message_handler(
269 DBusMessage *message,
270 const char *introspection,
271 const char *interfaces,
272 const BusBoundProperties *bound_properties) {
275 DBusMessage *reply = NULL;
281 dbus_error_init(&error);
283 if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
285 if (!(reply = dbus_message_new_method_return(message)))
288 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
291 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
292 const char *interface, *property;
293 const BusBoundProperties *bp;
294 const BusProperty *p;
296 DBusMessageIter iter, sub;
298 if (!dbus_message_get_args(
301 DBUS_TYPE_STRING, &interface,
302 DBUS_TYPE_STRING, &property,
304 return bus_send_error_reply(c, message, &error, -EINVAL);
306 for (bp = bound_properties; bp->interface; bp++) {
307 if (!streq(bp->interface, interface))
310 for (p = bp->properties; p->property; p++)
311 if (streq(p->property, property))
316 if (!nulstr_contains(interfaces, interface))
317 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
319 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
321 return bus_send_error_reply(c, message, &error, -EINVAL);
324 reply = dbus_message_new_method_return(message);
328 dbus_message_iter_init_append(reply, &iter);
330 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
333 data = (char*)bp->base + p->offset;
335 data = *(void**)data;
336 r = p->append(&sub, property, data);
341 dbus_message_unref(reply);
342 return bus_send_error_reply(c, message, NULL, r);
345 if (!dbus_message_iter_close_container(&iter, &sub))
348 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "GetAll") && bound_properties) {
349 const char *interface;
350 const BusBoundProperties *bp;
351 const BusProperty *p;
352 DBusMessageIter iter, sub, sub2, sub3;
354 if (!dbus_message_get_args(
357 DBUS_TYPE_STRING, &interface,
359 return bus_send_error_reply(c, message, &error, -EINVAL);
361 if (interface[0] && !nulstr_contains(interfaces, interface)) {
362 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
363 return bus_send_error_reply(c, message, &error, -EINVAL);
366 if (!(reply = dbus_message_new_method_return(message)))
369 dbus_message_iter_init_append(reply, &iter);
371 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
374 for (bp = bound_properties; bp->interface; bp++) {
375 if (interface[0] && !streq(bp->interface, interface))
378 for (p = bp->properties; p->property; p++) {
381 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
382 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
383 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
386 data = (char*)bp->base + p->offset;
388 data = *(void**)data;
389 r = p->append(&sub3, p->property, data);
394 dbus_message_unref(reply);
395 return bus_send_error_reply(c, message, NULL, r);
398 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
399 !dbus_message_iter_close_container(&sub, &sub2))
404 if (!dbus_message_iter_close_container(&iter, &sub))
407 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
408 const char *interface, *property;
409 DBusMessageIter iter;
410 const BusBoundProperties *bp;
411 const BusProperty *p;
415 DBusMessage *changed;
417 if (!dbus_message_iter_init(message, &iter) ||
418 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
419 return bus_send_error_reply(c, message, NULL, -EINVAL);
421 dbus_message_iter_get_basic(&iter, &interface);
423 if (!dbus_message_iter_next(&iter) ||
424 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
425 return bus_send_error_reply(c, message, NULL, -EINVAL);
427 dbus_message_iter_get_basic(&iter, &property);
429 if (!dbus_message_iter_next(&iter) ||
430 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
431 dbus_message_iter_has_next(&iter))
432 return bus_send_error_reply(c, message, NULL, -EINVAL);
434 for (bp = bound_properties; bp->interface; bp++) {
435 if (!streq(bp->interface, interface))
438 for (p = bp->properties; p->property; p++)
439 if (streq(p->property, property))
444 if (!nulstr_contains(interfaces, interface))
445 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
447 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
449 return bus_send_error_reply(c, message, &error, -EINVAL);
453 dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
454 return bus_send_error_reply(c, message, &error, -EINVAL);
457 dbus_message_iter_recurse(&iter, &sub);
459 sig = dbus_message_iter_get_signature(&sub);
463 if (!streq(sig, p->signature)) {
465 return bus_send_error_reply(c, message, NULL, -EINVAL);
469 data = (uint8_t*) bp->base + p->offset;
471 data = *(void**)data;
473 r = p->set(&sub, property, data);
477 return bus_send_error_reply(c, message, NULL, r);
479 reply = dbus_message_new_method_return(message);
483 /* Send out a signal about this, but it doesn't really
484 * matter if this fails, so eat all errors */
485 changed = bus_properties_changed_one_new(
486 dbus_message_get_path(message),
490 dbus_connection_send(c, changed, NULL);
491 dbus_message_unref(changed);
496 const char *interface = dbus_message_get_interface(message);
498 if (!interface || !nulstr_contains(interfaces, interface)) {
499 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
500 return bus_send_error_reply(c, message, &error, -EINVAL);
505 if (!dbus_connection_send(c, reply, NULL))
508 dbus_message_unref(reply);
509 return DBUS_HANDLER_RESULT_HANDLED;
512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
516 dbus_message_unref(reply);
518 dbus_error_free(&error);
520 return DBUS_HANDLER_RESULT_NEED_MEMORY;
523 int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
524 const char *t = data;
532 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
538 int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
544 return bus_append_strv_iter(i, t);
547 int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
557 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
563 int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
573 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
579 int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
584 /* Let's ensure that usec_t is actually 64bit, and hence this
585 * function can be used for usec_t */
586 assert_cc(sizeof(uint64_t) == sizeof(usec_t));
588 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
594 int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
599 /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
600 * 32bit, and hence this function can be used for
601 * pid_t/mode_t/uid_t/gid_t */
602 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
603 assert_cc(sizeof(uint32_t) == sizeof(mode_t));
604 assert_cc(sizeof(uint32_t) == sizeof(unsigned));
605 assert_cc(sizeof(uint32_t) == sizeof(uid_t));
606 assert_cc(sizeof(uint32_t) == sizeof(gid_t));
608 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
614 int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
619 assert_cc(sizeof(int32_t) == sizeof(int));
621 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
627 int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
634 u = (uint64_t) *(size_t*) data;
636 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
642 int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
649 u = (uint64_t) *(unsigned long*) data;
651 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
657 int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
664 l = (int64_t) *(long*) data;
666 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
672 int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
678 dbus_message_iter_get_basic(i, t);
682 const char *bus_errno_to_dbus(int error) {
687 return DBUS_ERROR_INVALID_ARGS;
690 return DBUS_ERROR_NO_MEMORY;
694 return DBUS_ERROR_ACCESS_DENIED;
697 return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
700 return DBUS_ERROR_FILE_NOT_FOUND;
703 return DBUS_ERROR_FILE_EXISTS;
707 return DBUS_ERROR_TIMEOUT;
710 return DBUS_ERROR_IO_ERROR;
715 return DBUS_ERROR_DISCONNECTED;
718 return DBUS_ERROR_FAILED;
721 DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
722 DBusMessage *reply = NULL;
723 const char *name, *text;
725 if (berror && dbus_error_is_set(berror)) {
727 text = berror->message;
729 name = bus_errno_to_dbus(error);
730 text = strerror(-error);
733 if (!(reply = dbus_message_new_error(message, name, text)))
736 if (!dbus_connection_send(c, reply, NULL))
739 dbus_message_unref(reply);
742 dbus_error_free(berror);
744 return DBUS_HANDLER_RESULT_HANDLED;
748 dbus_message_unref(reply);
751 dbus_error_free(berror);
753 return DBUS_HANDLER_RESULT_NEED_MEMORY;
756 DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
758 DBusMessageIter iter, sub;
764 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
768 dbus_message_iter_init_append(m, &iter);
770 /* We won't send any property values, since they might be
771 * large and sometimes not cheap to generated */
773 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
774 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
775 !dbus_message_iter_close_container(&iter, &sub) ||
776 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
779 NULSTR_FOREACH(i, properties)
780 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
783 if (!dbus_message_iter_close_container(&iter, &sub))
790 dbus_message_unref(m);
795 DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
797 DBusMessageIter iter, sub;
802 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
806 dbus_message_iter_init_append(m, &iter);
808 /* We won't send any property values, since they might be
809 * large and sometimes not cheap to generated */
811 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
812 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
813 !dbus_message_iter_close_container(&iter, &sub) ||
814 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
817 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
820 if (!dbus_message_iter_close_container(&iter, &sub))
827 dbus_message_unref(m);
832 uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
838 /* no watch flags for disabled watches */
839 if (!dbus_watch_get_enabled(bus_watch))
842 flags = dbus_watch_get_flags(bus_watch);
844 if (flags & DBUS_WATCH_READABLE)
846 if (flags & DBUS_WATCH_WRITABLE)
849 return events | EPOLLHUP | EPOLLERR;
852 unsigned bus_events_to_flags(uint32_t events) {
855 if (events & EPOLLIN)
856 flags |= DBUS_WATCH_READABLE;
857 if (events & EPOLLOUT)
858 flags |= DBUS_WATCH_WRITABLE;
859 if (events & EPOLLHUP)
860 flags |= DBUS_WATCH_HANGUP;
861 if (events & EPOLLERR)
862 flags |= DBUS_WATCH_ERROR;
867 int bus_parse_strv(DBusMessage *m, char ***_l) {
868 DBusMessageIter iter;
873 if (!dbus_message_iter_init(m, &iter))
876 return bus_parse_strv_iter(&iter, _l);
879 int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
881 unsigned n = 0, i = 0;
887 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
888 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
891 dbus_message_iter_recurse(iter, &sub);
893 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
895 dbus_message_iter_next(&sub);
898 if (!(l = new(char*, n+1)))
901 dbus_message_iter_recurse(iter, &sub);
903 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
906 assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
907 dbus_message_iter_get_basic(&sub, &s);
909 if (!(l[i++] = strdup(s))) {
914 dbus_message_iter_next(&sub);
926 int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
931 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
935 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
938 if (!dbus_message_iter_close_container(iter, &sub))
944 int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
949 if (dbus_message_iter_get_arg_type(iter) != type)
952 dbus_message_iter_get_basic(iter, data);
954 if (!dbus_message_iter_next(iter) != !next)
960 int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
964 switch (dbus_message_iter_get_arg_type(iter)) {
966 case DBUS_TYPE_STRING: {
968 dbus_message_iter_get_basic(iter, &s);
970 if (all || !isempty(s))
971 printf("%s=%s\n", name, s);
976 case DBUS_TYPE_BOOLEAN: {
979 dbus_message_iter_get_basic(iter, &b);
980 printf("%s=%s\n", name, yes_no(b));
985 case DBUS_TYPE_UINT64: {
987 dbus_message_iter_get_basic(iter, &u);
989 /* Yes, heuristics! But we can change this check
990 * should it turn out to not be sufficient */
992 if (endswith(name, "Timestamp")) {
993 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
995 t = format_timestamp(timestamp, sizeof(timestamp), u);
997 printf("%s=%s\n", name, strempty(t));
999 } else if (strstr(name, "USec")) {
1000 char timespan[FORMAT_TIMESPAN_MAX];
1002 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u));
1004 printf("%s=%llu\n", name, (unsigned long long) u);
1009 case DBUS_TYPE_UINT32: {
1011 dbus_message_iter_get_basic(iter, &u);
1013 if (strstr(name, "UMask") || strstr(name, "Mode"))
1014 printf("%s=%04o\n", name, u);
1016 printf("%s=%u\n", name, (unsigned) u);
1021 case DBUS_TYPE_INT32: {
1023 dbus_message_iter_get_basic(iter, &i);
1025 printf("%s=%i\n", name, (int) i);
1029 case DBUS_TYPE_DOUBLE: {
1031 dbus_message_iter_get_basic(iter, &d);
1033 printf("%s=%g\n", name, d);
1037 case DBUS_TYPE_ARRAY:
1039 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
1040 DBusMessageIter sub;
1043 dbus_message_iter_recurse(iter, &sub);
1045 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1046 printf("%s=", name);
1048 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1051 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
1052 dbus_message_iter_get_basic(&sub, &s);
1053 printf("%s%s", space ? " " : "", s);
1056 dbus_message_iter_next(&sub);
1064 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
1065 DBusMessageIter sub;
1067 dbus_message_iter_recurse(iter, &sub);
1069 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1070 printf("%s=", name);
1072 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1075 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
1076 dbus_message_iter_get_basic(&sub, &u);
1079 dbus_message_iter_next(&sub);
1087 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_UINT32) {
1088 DBusMessageIter sub;
1090 dbus_message_iter_recurse(iter, &sub);
1092 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1093 printf("%s=", name);
1095 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1098 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32);
1099 dbus_message_iter_get_basic(&sub, &u);
1102 dbus_message_iter_next(&sub);
1117 static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
1119 DBusConnection *bus = userdata;
1121 assert_se(reply = dbus_pending_call_steal_reply(pending));
1122 dbus_message_unref(reply);
1124 dbus_connection_close(bus);
1127 void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
1128 DBusMessage *m = NULL;
1129 DBusPendingCall *pending = NULL;
1133 /* We unregister the name here, but we continue to process
1134 * requests, until we get the response for it, so that all
1135 * requests are guaranteed to be processed. */
1137 m = dbus_message_new_method_call(
1140 DBUS_INTERFACE_DBUS,
1145 if (!dbus_message_append_args(
1152 if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
1155 if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
1158 dbus_message_unref(m);
1159 dbus_pending_call_unref(pending);
1167 dbus_pending_call_cancel(pending);
1168 dbus_pending_call_unref(pending);
1172 dbus_message_unref(m);
1175 DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
1176 usec_t *remain_until = userdata;
1180 assert(remain_until);
1182 /* Every time we get a new message we reset out timeout */
1183 *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
1185 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
1186 dbus_connection_close(bus);
1188 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1191 /* This mimics dbus_bus_get_unix_user() */
1192 pid_t bus_get_unix_process_id(
1193 DBusConnection *connection,
1197 DBusMessage *m = NULL, *reply = NULL;
1200 m = dbus_message_new_method_call(
1203 DBUS_INTERFACE_DBUS,
1204 "GetConnectionUnixProcessID");
1206 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
1210 if (!dbus_message_append_args(
1212 DBUS_TYPE_STRING, &name,
1213 DBUS_TYPE_INVALID)) {
1214 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
1218 reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
1222 if (dbus_set_error_from_message(error, reply))
1225 if (!dbus_message_get_args(
1227 DBUS_TYPE_UINT32, &pid,
1233 dbus_message_unref(m);
1236 dbus_message_unref(reply);
1241 bool bus_error_is_no_service(const DBusError *error) {
1244 if (!dbus_error_is_set(error))
1247 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
1250 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
1253 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
1256 int bus_method_call_with_reply(DBusConnection *bus,
1257 const char *destination,
1259 const char *interface,
1261 DBusMessage **return_reply,
1262 DBusError *return_error,
1263 int first_arg_type, ...) {
1265 DBusMessage *m, *reply;
1269 dbus_error_init(&error);
1272 m = dbus_message_new_method_call(destination, path, interface, method);
1278 va_start(ap, first_arg_type);
1279 if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
1281 dbus_message_unref(m);
1287 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1288 dbus_message_unref(m);
1291 log_error("Failed to issue method call: %s", bus_error_message(&error));
1292 if (bus_error_is_no_service(&error))
1294 else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
1296 else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
1303 *return_reply = reply;
1305 dbus_message_unref(reply);
1308 *return_error=error;
1310 dbus_error_free(&error);