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"
39 int bus_check_peercred(DBusConnection *c) {
46 assert_se(dbus_connection_get_unix_fd(c, &fd));
48 l = sizeof(struct ucred);
49 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0) {
50 log_error("SO_PEERCRED failed: %m");
54 if (l != sizeof(struct ucred)) {
55 log_error("SO_PEERCRED returned wrong size.");
59 if (ucred.uid != 0 && ucred.uid != geteuid())
65 static int sync_auth(DBusConnection *bus, DBusError *error) {
70 /* This complexity should probably move into D-Bus itself:
72 * https://bugs.freedesktop.org/show_bug.cgi?id=35189 */
74 begin = tstamp = now(CLOCK_MONOTONIC);
77 if (tstamp > begin + DEFAULT_TIMEOUT_USEC)
80 if (dbus_connection_get_is_authenticated(bus))
83 if (!dbus_connection_read_write_dispatch(bus, ((begin + DEFAULT_TIMEOUT_USEC - tstamp) + USEC_PER_MSEC - 1) / USEC_PER_MSEC))
86 tstamp = now(CLOCK_MONOTONIC);
89 if (!dbus_connection_get_is_connected(bus)) {
90 dbus_set_error_const(error, DBUS_ERROR_NO_SERVER, "Connection terminated during authentication.");
94 if (!dbus_connection_get_is_authenticated(bus)) {
95 dbus_set_error_const(error, DBUS_ERROR_TIMEOUT, "Failed to authenticate in time.");
102 int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) {
103 DBusConnection *bus = NULL;
109 if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) {
110 /* If we are root, then let's talk directly to the
111 * system instance, instead of going via the bus */
113 bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
118 if (t == DBUS_BUS_SESSION) {
121 /* If we are supposed to talk to the instance,
122 * try via XDG_RUNTIME_DIR first, then
123 * fallback to normal bus access */
125 e = secure_getenv("XDG_RUNTIME_DIR");
129 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
132 bus = dbus_connection_open_private(p, NULL);
138 bus = dbus_bus_get_private(t, error);
146 dbus_connection_set_exit_on_disconnect(bus, FALSE);
149 if (bus_check_peercred(bus) < 0) {
150 dbus_connection_close(bus);
151 dbus_connection_unref(bus);
153 dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus.");
158 r = sync_auth(bus, error);
160 dbus_connection_close(bus);
161 dbus_connection_unref(bus);
172 int bus_connect_system_ssh(const char *user, const char *host, DBusConnection **_bus, DBusError *error) {
178 assert(user || host);
181 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40%s,argv3=systemd-stdio-bridge", user, host);
183 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s%%40localhost,argv3=systemd-stdio-bridge", user);
185 asprintf(&p, "unixexec:path=ssh,argv1=-xT,argv2=%s,argv3=systemd-stdio-bridge", host);
188 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
192 bus = dbus_connection_open_private(p, error);
198 dbus_connection_set_exit_on_disconnect(bus, FALSE);
200 if ((r = sync_auth(bus, error)) < 0) {
201 dbus_connection_close(bus);
202 dbus_connection_unref(bus);
206 if (!dbus_bus_register(bus, error)) {
207 dbus_connection_close(bus);
208 dbus_connection_unref(bus);
216 int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
222 /* Don't bother with PolicyKit if we are root */
224 return bus_connect(DBUS_BUS_SYSTEM, _bus, NULL, error);
226 bus = dbus_connection_open_private("unixexec:path=pkexec,argv1=" SYSTEMD_STDIO_BRIDGE_BINARY_PATH, error);
230 dbus_connection_set_exit_on_disconnect(bus, FALSE);
232 r = sync_auth(bus, error);
234 dbus_connection_close(bus);
235 dbus_connection_unref(bus);
239 if (!dbus_bus_register(bus, error)) {
240 dbus_connection_close(bus);
241 dbus_connection_unref(bus);
249 const char *bus_error_message(const DBusError *error) {
253 /* Sometimes the D-Bus server is a little bit too verbose with
254 * its error messages, so let's override them here */
255 if (dbus_error_has_name(error, DBUS_ERROR_ACCESS_DENIED))
256 return "Access denied";
258 return error->message;
261 const char *bus_error(const DBusError *error, int err) {
262 if (error && dbus_error_is_set(error))
263 return bus_error_message(error);
265 return strerror(err < 0 ? -err : err);
268 DBusHandlerResult bus_default_message_handler(
270 DBusMessage *message,
271 const char *introspection,
272 const char *interfaces,
273 const BusBoundProperties *bound_properties) {
276 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
282 dbus_error_init(&error);
284 if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
286 reply = dbus_message_new_method_return(message);
290 if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
293 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Get") && bound_properties) {
294 const char *interface, *property;
295 const BusBoundProperties *bp;
296 const BusProperty *p;
298 DBusMessageIter iter, sub;
300 if (!dbus_message_get_args(
303 DBUS_TYPE_STRING, &interface,
304 DBUS_TYPE_STRING, &property,
306 return bus_send_error_reply(c, message, &error, -EINVAL);
308 for (bp = bound_properties; bp->interface; bp++) {
309 if (!streq(bp->interface, interface))
312 for (p = bp->properties; p->property; p++)
313 if (streq(p->property, property))
318 if (!nulstr_contains(interfaces, interface))
319 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
321 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
323 return bus_send_error_reply(c, message, &error, -EINVAL);
326 reply = dbus_message_new_method_return(message);
330 dbus_message_iter_init_append(reply, &iter);
332 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, p->signature, &sub))
335 data = (char*)bp->base + p->offset;
337 data = *(void**)data;
339 r = p->append(&sub, property, data);
343 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 reply = dbus_message_new_method_return(message);
370 dbus_message_iter_init_append(reply, &iter);
372 if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub))
375 for (bp = bound_properties; bp->interface; bp++) {
376 if (interface[0] && !streq(bp->interface, interface))
379 for (p = bp->properties; p->property; p++) {
382 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_DICT_ENTRY, NULL, &sub2) ||
383 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &p->property) ||
384 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_VARIANT, p->signature, &sub3))
387 data = (char*)bp->base + p->offset;
389 data = *(void**)data;
390 r = p->append(&sub3, p->property, data);
394 return bus_send_error_reply(c, message, NULL, r);
396 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
397 !dbus_message_iter_close_container(&sub, &sub2))
402 if (!dbus_message_iter_close_container(&iter, &sub))
405 } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set") && bound_properties) {
406 const char *interface, *property;
407 DBusMessageIter iter;
408 const BusBoundProperties *bp;
409 const BusProperty *p;
413 DBusMessage *changed;
415 if (!dbus_message_iter_init(message, &iter) ||
416 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
417 return bus_send_error_reply(c, message, NULL, -EINVAL);
419 dbus_message_iter_get_basic(&iter, &interface);
421 if (!dbus_message_iter_next(&iter) ||
422 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
423 return bus_send_error_reply(c, message, NULL, -EINVAL);
425 dbus_message_iter_get_basic(&iter, &property);
427 if (!dbus_message_iter_next(&iter) ||
428 dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT ||
429 dbus_message_iter_has_next(&iter))
430 return bus_send_error_reply(c, message, NULL, -EINVAL);
432 for (bp = bound_properties; bp->interface; bp++) {
433 if (!streq(bp->interface, interface))
436 for (p = bp->properties; p->property; p++)
437 if (streq(p->property, property))
442 if (!nulstr_contains(interfaces, interface))
443 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
445 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_PROPERTY, "Unknown property");
447 return bus_send_error_reply(c, message, &error, -EINVAL);
451 dbus_set_error_const(&error, DBUS_ERROR_PROPERTY_READ_ONLY, "Property read-only");
452 return bus_send_error_reply(c, message, &error, -EINVAL);
455 dbus_message_iter_recurse(&iter, &sub);
457 sig = dbus_message_iter_get_signature(&sub);
461 if (!streq(sig, p->signature)) {
463 return bus_send_error_reply(c, message, NULL, -EINVAL);
467 data = (uint8_t*) bp->base + p->offset;
469 data = *(void**)data;
471 r = p->set(&sub, property, data);
475 return bus_send_error_reply(c, message, NULL, r);
477 reply = dbus_message_new_method_return(message);
481 /* Send out a signal about this, but it doesn't really
482 * matter if this fails, so eat all errors */
483 changed = bus_properties_changed_one_new(
484 dbus_message_get_path(message),
488 dbus_connection_send(c, changed, NULL);
489 dbus_message_unref(changed);
494 const char *interface = dbus_message_get_interface(message);
496 if (!interface || !nulstr_contains(interfaces, interface)) {
497 dbus_set_error_const(&error, DBUS_ERROR_UNKNOWN_INTERFACE, "Unknown interface");
498 return bus_send_error_reply(c, message, &error, -EINVAL);
503 if (!bus_maybe_send_reply(c, message, reply))
506 return DBUS_HANDLER_RESULT_HANDLED;
509 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
512 dbus_error_free(&error);
514 return DBUS_HANDLER_RESULT_NEED_MEMORY;
517 int bus_property_append_string(DBusMessageIter *i, const char *property, void *data) {
518 const char *t = data;
526 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t))
532 int bus_property_append_strv(DBusMessageIter *i, const char *property, void *data) {
538 return bus_append_strv_iter(i, t);
541 int bus_property_append_bool(DBusMessageIter *i, const char *property, void *data) {
551 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
557 int bus_property_append_tristate_false(DBusMessageIter *i, const char *property, void *data) {
567 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &db))
573 int bus_property_append_uint64(DBusMessageIter *i, const char *property, void *data) {
578 /* Let's ensure that usec_t is actually 64bit, and hence this
579 * function can be used for usec_t */
580 assert_cc(sizeof(uint64_t) == sizeof(usec_t));
582 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, data))
588 int bus_property_append_uint32(DBusMessageIter *i, const char *property, void *data) {
593 /* Let's ensure that pid_t, mode_t, uid_t, gid_t are actually
594 * 32bit, and hence this function can be used for
595 * pid_t/mode_t/uid_t/gid_t */
596 assert_cc(sizeof(uint32_t) == sizeof(pid_t));
597 assert_cc(sizeof(uint32_t) == sizeof(mode_t));
598 assert_cc(sizeof(uint32_t) == sizeof(unsigned));
599 assert_cc(sizeof(uint32_t) == sizeof(uid_t));
600 assert_cc(sizeof(uint32_t) == sizeof(gid_t));
602 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, data))
608 int bus_property_append_int32(DBusMessageIter *i, const char *property, void *data) {
613 assert_cc(sizeof(int32_t) == sizeof(int));
615 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, data))
621 int bus_property_append_size(DBusMessageIter *i, const char *property, void *data) {
628 u = (uint64_t) *(size_t*) data;
630 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
636 int bus_property_append_ul(DBusMessageIter *i, const char *property, void *data) {
643 u = (uint64_t) *(unsigned long*) data;
645 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
651 int bus_property_append_long(DBusMessageIter *i, const char *property, void *data) {
658 l = (int64_t) *(long*) data;
660 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT64, &l))
666 int bus_property_set_uint64(DBusMessageIter *i, const char *property, void *data) {
672 dbus_message_iter_get_basic(i, t);
676 const char *bus_errno_to_dbus(int error) {
681 return DBUS_ERROR_INVALID_ARGS;
684 return DBUS_ERROR_NO_MEMORY;
688 return DBUS_ERROR_ACCESS_DENIED;
691 return DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN;
694 return DBUS_ERROR_FILE_NOT_FOUND;
697 return DBUS_ERROR_FILE_EXISTS;
701 return DBUS_ERROR_TIMEOUT;
704 return DBUS_ERROR_IO_ERROR;
709 return DBUS_ERROR_DISCONNECTED;
712 return DBUS_ERROR_FAILED;
715 dbus_bool_t bus_maybe_send_reply (DBusConnection *c,
716 DBusMessage *message,
719 /* Some parts of systemd "reply" to signals, which of course
720 * have the no-reply flag set. We will be defensive here and
721 * still send out a reply if we're passed a signal.
723 if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
724 dbus_message_get_no_reply(message))
726 return dbus_connection_send(c, reply, NULL);
729 DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
730 _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
731 const char *name, *text;
733 if (berror && dbus_error_is_set(berror)) {
735 text = berror->message;
737 name = bus_errno_to_dbus(error);
738 text = strerror(-error);
741 reply = dbus_message_new_error(message, name, text);
745 if (!bus_maybe_send_reply(c, message, reply))
749 dbus_error_free(berror);
751 return DBUS_HANDLER_RESULT_HANDLED;
755 dbus_message_unref(reply);
758 dbus_error_free(berror);
760 return DBUS_HANDLER_RESULT_NEED_MEMORY;
763 DBusMessage* bus_properties_changed_new(const char *path, const char *interface, const char *properties) {
765 DBusMessageIter iter, sub;
771 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
775 dbus_message_iter_init_append(m, &iter);
777 /* We won't send any property values, since they might be
778 * large and sometimes not cheap to generated */
780 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
781 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
782 !dbus_message_iter_close_container(&iter, &sub) ||
783 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
786 NULSTR_FOREACH(i, properties)
787 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &i))
790 if (!dbus_message_iter_close_container(&iter, &sub))
797 dbus_message_unref(m);
802 DBusMessage* bus_properties_changed_one_new(const char *path, const char *interface, const char *property) {
804 DBusMessageIter iter, sub;
809 m = dbus_message_new_signal(path, "org.freedesktop.DBus.Properties", "PropertiesChanged");
813 dbus_message_iter_init_append(m, &iter);
815 /* We won't send any property values, since they might be
816 * large and sometimes not cheap to generated */
818 if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface) ||
819 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &sub) ||
820 !dbus_message_iter_close_container(&iter, &sub) ||
821 !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &sub))
824 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &property))
827 if (!dbus_message_iter_close_container(&iter, &sub))
834 dbus_message_unref(m);
839 uint32_t bus_flags_to_events(DBusWatch *bus_watch) {
845 /* no watch flags for disabled watches */
846 if (!dbus_watch_get_enabled(bus_watch))
849 flags = dbus_watch_get_flags(bus_watch);
851 if (flags & DBUS_WATCH_READABLE)
853 if (flags & DBUS_WATCH_WRITABLE)
856 return events | EPOLLHUP | EPOLLERR;
859 unsigned bus_events_to_flags(uint32_t events) {
862 if (events & EPOLLIN)
863 flags |= DBUS_WATCH_READABLE;
864 if (events & EPOLLOUT)
865 flags |= DBUS_WATCH_WRITABLE;
866 if (events & EPOLLHUP)
867 flags |= DBUS_WATCH_HANGUP;
868 if (events & EPOLLERR)
869 flags |= DBUS_WATCH_ERROR;
874 int bus_parse_strv(DBusMessage *m, char ***_l) {
875 DBusMessageIter iter;
880 if (!dbus_message_iter_init(m, &iter))
883 return bus_parse_strv_iter(&iter, _l);
886 int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
888 unsigned n = 0, i = 0;
894 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
895 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRING)
898 dbus_message_iter_recurse(iter, &sub);
900 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
902 dbus_message_iter_next(&sub);
909 dbus_message_iter_recurse(iter, &sub);
911 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
914 assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
915 dbus_message_iter_get_basic(&sub, &s);
917 if (!(l[i++] = strdup(s))) {
922 dbus_message_iter_next(&sub);
934 int bus_parse_strv_pairs_iter(DBusMessageIter *iter, char ***_l) {
935 DBusMessageIter sub, sub2;
936 unsigned n = 0, i = 0;
942 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY ||
943 dbus_message_iter_get_element_type(iter) != DBUS_TYPE_STRUCT)
946 dbus_message_iter_recurse(iter, &sub);
948 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
950 dbus_message_iter_next(&sub);
953 l = new(char*, n*2+1);
957 dbus_message_iter_recurse(iter, &sub);
959 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
962 assert_se(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT);
964 dbus_message_iter_recurse(&sub, &sub2);
966 if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &a, true) < 0 ||
967 bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &b, false) < 0)
983 dbus_message_iter_next(&sub);
995 int bus_parse_unit_info(DBusMessageIter *iter, struct unit_info *u) {
1001 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_STRUCT)
1004 dbus_message_iter_recurse(iter, &sub);
1006 if (bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->id, true) < 0 ||
1007 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->description, true) < 0 ||
1008 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->load_state, true) < 0 ||
1009 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->active_state, true) < 0 ||
1010 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->sub_state, true) < 0 ||
1011 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->following, true) < 0 ||
1012 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->unit_path, true) < 0 ||
1013 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_UINT32, &u->job_id, true) < 0 ||
1014 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_STRING, &u->job_type, true) < 0 ||
1015 bus_iter_get_basic_and_next(&sub, DBUS_TYPE_OBJECT_PATH, &u->job_path, false) < 0) {
1016 log_error("Failed to parse reply.");
1023 int bus_append_strv_iter(DBusMessageIter *iter, char **l) {
1024 DBusMessageIter sub;
1028 if (!dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "s", &sub))
1032 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, l))
1035 if (!dbus_message_iter_close_container(iter, &sub))
1041 int bus_iter_get_basic_and_next(DBusMessageIter *iter, int type, void *data, bool next) {
1046 if (dbus_message_iter_get_arg_type(iter) != type)
1049 dbus_message_iter_get_basic(iter, data);
1051 if (!dbus_message_iter_next(iter) != !next)
1057 int generic_print_property(const char *name, DBusMessageIter *iter, bool all) {
1061 switch (dbus_message_iter_get_arg_type(iter)) {
1063 case DBUS_TYPE_STRING: {
1065 dbus_message_iter_get_basic(iter, &s);
1067 if (all || !isempty(s))
1068 printf("%s=%s\n", name, s);
1073 case DBUS_TYPE_BOOLEAN: {
1076 dbus_message_iter_get_basic(iter, &b);
1077 printf("%s=%s\n", name, yes_no(b));
1082 case DBUS_TYPE_UINT64: {
1084 dbus_message_iter_get_basic(iter, &u);
1086 /* Yes, heuristics! But we can change this check
1087 * should it turn out to not be sufficient */
1089 if (endswith(name, "Timestamp")) {
1090 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
1092 t = format_timestamp(timestamp, sizeof(timestamp), u);
1094 printf("%s=%s\n", name, strempty(t));
1096 } else if (strstr(name, "USec")) {
1097 char timespan[FORMAT_TIMESPAN_MAX];
1099 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
1101 printf("%s=%llu\n", name, (unsigned long long) u);
1106 case DBUS_TYPE_UINT32: {
1108 dbus_message_iter_get_basic(iter, &u);
1110 if (strstr(name, "UMask") || strstr(name, "Mode"))
1111 printf("%s=%04o\n", name, u);
1113 printf("%s=%u\n", name, (unsigned) u);
1118 case DBUS_TYPE_INT32: {
1120 dbus_message_iter_get_basic(iter, &i);
1122 printf("%s=%i\n", name, (int) i);
1126 case DBUS_TYPE_DOUBLE: {
1128 dbus_message_iter_get_basic(iter, &d);
1130 printf("%s=%g\n", name, d);
1134 case DBUS_TYPE_ARRAY:
1136 if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING) {
1137 DBusMessageIter sub;
1140 dbus_message_iter_recurse(iter, &sub);
1142 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1143 printf("%s=", name);
1145 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1148 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING);
1149 dbus_message_iter_get_basic(&sub, &s);
1150 printf("%s%s", space ? " " : "", s);
1153 dbus_message_iter_next(&sub);
1161 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
1162 DBusMessageIter sub;
1164 dbus_message_iter_recurse(iter, &sub);
1166 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1167 printf("%s=", name);
1169 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1172 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
1173 dbus_message_iter_get_basic(&sub, &u);
1176 dbus_message_iter_next(&sub);
1184 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_UINT32) {
1185 DBusMessageIter sub;
1187 dbus_message_iter_recurse(iter, &sub);
1189 dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1190 printf("%s=", name);
1192 while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
1195 assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32);
1196 dbus_message_iter_get_basic(&sub, &u);
1199 dbus_message_iter_next(&sub);
1214 static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
1216 DBusConnection *bus = userdata;
1218 assert_se(reply = dbus_pending_call_steal_reply(pending));
1219 dbus_message_unref(reply);
1221 dbus_connection_close(bus);
1224 void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
1225 _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
1226 DBusPendingCall *pending = NULL;
1230 /* We unregister the name here, but we continue to process
1231 * requests, until we get the response for it, so that all
1232 * requests are guaranteed to be processed. */
1234 m = dbus_message_new_method_call(
1237 DBUS_INTERFACE_DBUS,
1242 if (!dbus_message_append_args(
1249 if (!dbus_connection_send_with_reply(bus, m, &pending, -1))
1252 if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
1255 dbus_pending_call_unref(pending);
1263 dbus_pending_call_cancel(pending);
1264 dbus_pending_call_unref(pending);
1268 DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
1269 usec_t *remain_until = userdata;
1273 assert(remain_until);
1275 /* Every time we get a new message we reset out timeout */
1276 *remain_until = now(CLOCK_MONOTONIC) + DEFAULT_EXIT_USEC;
1278 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
1279 dbus_connection_close(bus);
1281 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1284 /* This mimics dbus_bus_get_unix_user() */
1285 pid_t bus_get_unix_process_id(
1286 DBusConnection *connection,
1290 _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
1293 m = dbus_message_new_method_call(
1296 DBUS_INTERFACE_DBUS,
1297 "GetConnectionUnixProcessID");
1299 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
1303 if (!dbus_message_append_args(
1305 DBUS_TYPE_STRING, &name,
1306 DBUS_TYPE_INVALID)) {
1307 dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
1311 reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
1315 if (dbus_set_error_from_message(error, reply))
1318 if (!dbus_message_get_args(
1320 DBUS_TYPE_UINT32, &pid,
1327 bool bus_error_is_no_service(const DBusError *error) {
1330 if (!dbus_error_is_set(error))
1333 if (dbus_error_has_name(error, DBUS_ERROR_NAME_HAS_NO_OWNER))
1336 if (dbus_error_has_name(error, DBUS_ERROR_SERVICE_UNKNOWN))
1339 return startswith(error->name, "org.freedesktop.DBus.Error.Spawn.");
1342 int bus_method_call_with_reply(
1343 DBusConnection *bus,
1344 const char *destination,
1346 const char *interface,
1348 DBusMessage **return_reply,
1349 DBusError *return_error,
1350 int first_arg_type, ...) {
1353 _cleanup_dbus_message_unref_ DBusMessage *m = NULL;
1358 dbus_error_init(&error);
1361 m = dbus_message_new_method_call(destination, path, interface, method);
1367 va_start(ap, first_arg_type);
1368 if (!dbus_message_append_args_valist(m, first_arg_type, ap)) {
1375 reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
1378 log_error("Failed to issue method call: %s", bus_error_message(&error));
1380 if (bus_error_is_no_service(&error))
1382 else if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED))
1384 else if (dbus_error_has_name(&error, DBUS_ERROR_NO_REPLY))
1392 *return_reply = reply;
1394 dbus_message_unref(reply);
1398 *return_error = error;
1400 dbus_error_free(&error);
1405 void bus_message_unrefp(DBusMessage **reply) {
1412 dbus_message_unref(*reply);
1415 const char *bus_message_get_sender_with_fallback(DBusMessage *m) {
1420 s = dbus_message_get_sender(m);
1424 /* When the message came in from a direct connection the
1425 * message will have no sender. We fix that here. */
1427 return ":no-sender";