1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
27 #include <sys/ioctl.h>
28 #include <sys/resource.h>
29 #include <sys/socket.h>
32 #include "sd-bus-protocol.h"
34 #include "sd-daemon.h"
38 #include "alloc-util.h"
39 #include "bus-internal.h"
40 #include "bus-label.h"
41 #include "bus-message.h"
44 #include "cgroup-util.h"
49 #include "mount-util.h"
51 #include "parse-util.h"
52 #include "proc-cmdline.h"
53 //#include "rlimit-util.h"
54 #include "stdio-util.h"
56 #include "user-util.h"
58 #if 0 /// UNNEEDED by elogind
59 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
60 sd_event *e = userdata;
65 sd_bus_close(sd_bus_message_get_bus(m));
71 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
80 /* We unregister the name here and then wait for the
81 * NameOwnerChanged signal for this event to arrive before we
82 * quit. We do this in order to make sure that any queued
83 * requests are still processed before we really exit. */
85 r = sd_bus_get_unique_name(bus, &unique);
90 "sender='org.freedesktop.DBus',"
92 "interface='org.freedesktop.DBus',"
93 "member='NameOwnerChanged',"
94 "path='/org/freedesktop/DBus',"
96 "arg1='", unique, "',",
99 r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
103 r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
110 int bus_event_loop_with_idle(
115 check_idle_t check_idle,
117 bool exiting = false;
127 r = sd_event_get_state(e);
130 if (r == SD_EVENT_FINISHED)
134 idle = check_idle(userdata);
138 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
142 if (r == 0 && !exiting && idle) {
144 r = sd_bus_try_close(bus);
148 /* Fallback for dbus1 connections: we
149 * unregister the name and wait for the
150 * response to come through for it */
151 if (r == -EOPNOTSUPP) {
153 /* Inform the service manager that we
154 * are going down, so that it will
155 * queue all further start requests,
156 * instead of assuming we are already
158 sd_notify(false, "STOPPING=1");
160 r = bus_async_unregister_and_exit(e, bus, name);
176 r = sd_event_get_exit_code(e, &code);
184 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
185 _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
186 int r, has_owner = 0;
191 r = sd_bus_call_method(c,
192 "org.freedesktop.DBus",
193 "/org/freedesktop/dbus",
194 "org.freedesktop.DBus",
203 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
205 return sd_bus_error_set_errno(error, r);
210 static int check_good_user(sd_bus_message *m, uid_t good_user) {
211 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
217 if (good_user == UID_INVALID)
220 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
224 /* Don't trust augmented credentials for authorization */
225 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
227 r = sd_bus_creds_get_euid(creds, &sender_uid);
231 return sender_uid == good_user;
235 sd_bus_message *call,
238 const char **details,
248 /* Tests non-interactively! */
250 r = check_good_user(call, good_user);
254 r = sd_bus_query_sender_privilege(call, capability);
261 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
262 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
263 int authorized = false, challenge = false;
264 const char *sender, **k, **v;
266 sender = sd_bus_message_get_sender(call);
270 r = sd_bus_message_new_method_call(
273 "org.freedesktop.PolicyKit1",
274 "/org/freedesktop/PolicyKit1/Authority",
275 "org.freedesktop.PolicyKit1.Authority",
276 "CheckAuthorization");
280 r = sd_bus_message_append(
283 "system-bus-name", 1, "name", "s", sender,
288 r = sd_bus_message_open_container(request, 'a', "{ss}");
292 STRV_FOREACH_PAIR(k, v, details) {
293 r = sd_bus_message_append(request, "{ss}", *k, *v);
298 r = sd_bus_message_close_container(request);
302 r = sd_bus_message_append(request, "us", 0, NULL);
306 r = sd_bus_call(call->bus, request, 0, e, &reply);
308 /* Treat no PK available as access denied */
309 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
310 sd_bus_error_free(e);
317 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
321 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
329 *_challenge = challenge;
340 typedef struct AsyncPolkitQuery {
341 sd_bus_message *request, *reply;
342 sd_bus_message_handler_t callback;
348 static void async_polkit_query_free(AsyncPolkitQuery *q) {
353 sd_bus_slot_unref(q->slot);
355 if (q->registry && q->request)
356 hashmap_remove(q->registry, q->request);
358 sd_bus_message_unref(q->request);
359 sd_bus_message_unref(q->reply);
364 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
365 _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
366 AsyncPolkitQuery *q = userdata;
372 q->slot = sd_bus_slot_unref(q->slot);
373 q->reply = sd_bus_message_ref(reply);
375 r = sd_bus_message_rewind(q->request, true);
377 r = sd_bus_reply_method_errno(q->request, r, NULL);
381 r = q->callback(q->request, q->userdata, &error_buffer);
382 r = bus_maybe_reply_error(q->request, r, &error_buffer);
385 async_polkit_query_free(q);
392 int bus_verify_polkit_async(
393 sd_bus_message *call,
396 const char **details,
400 sd_bus_error *error) {
403 _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
405 const char *sender, **k, **v;
406 sd_bus_message_handler_t callback;
416 r = check_good_user(call, good_user);
421 q = hashmap_get(*registry, call);
423 int authorized, challenge;
425 /* This is the second invocation of this function, and
426 * there's already a response from polkit, let's
430 if (sd_bus_message_is_method_error(q->reply, NULL)) {
431 const sd_bus_error *e;
433 /* Copy error from polkit reply */
434 e = sd_bus_message_get_error(q->reply);
435 sd_bus_error_copy(error, e);
437 /* Treat no PK available as access denied */
438 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
441 return -sd_bus_error_get_errno(e);
444 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
446 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
455 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
461 r = sd_bus_query_sender_privilege(call, capability);
468 if (sd_bus_get_current_message(call->bus) != call)
471 callback = sd_bus_get_current_handler(call->bus);
475 userdata = sd_bus_get_current_userdata(call->bus);
477 sender = sd_bus_message_get_sender(call);
481 c = sd_bus_message_get_allow_interactive_authorization(call);
487 r = hashmap_ensure_allocated(registry, NULL);
491 r = sd_bus_message_new_method_call(
494 "org.freedesktop.PolicyKit1",
495 "/org/freedesktop/PolicyKit1/Authority",
496 "org.freedesktop.PolicyKit1.Authority",
497 "CheckAuthorization");
501 r = sd_bus_message_append(
504 "system-bus-name", 1, "name", "s", sender,
509 r = sd_bus_message_open_container(pk, 'a', "{ss}");
513 STRV_FOREACH_PAIR(k, v, details) {
514 r = sd_bus_message_append(pk, "{ss}", *k, *v);
519 r = sd_bus_message_close_container(pk);
523 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
527 q = new0(AsyncPolkitQuery, 1);
531 q->request = sd_bus_message_ref(call);
532 q->callback = callback;
533 q->userdata = userdata;
535 r = hashmap_put(*registry, call, q);
537 async_polkit_query_free(q);
541 q->registry = *registry;
543 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
545 async_polkit_query_free(q);
555 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
557 hashmap_free_with_destructor(registry, async_polkit_query_free);
561 #if 0 /// UNNEEDED by elogind
562 int bus_check_peercred(sd_bus *c) {
568 fd = sd_bus_get_fd(c);
572 r = getpeercred(fd, &ucred);
576 if (ucred.uid != 0 && ucred.uid != geteuid())
582 int bus_connect_system_systemd(sd_bus **_bus) {
583 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
589 return sd_bus_default_system(_bus);
591 /* If we are root then let's talk directly to the system
592 * instance, instead of going via the bus */
594 r = sd_bus_new(&bus);
598 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
602 r = sd_bus_start(bus);
604 return sd_bus_default_system(_bus);
606 r = bus_check_peercred(bus);
616 int bus_connect_user_systemd(sd_bus **_bus) {
617 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
618 _cleanup_free_ char *ee = NULL;
624 e = secure_getenv("XDG_RUNTIME_DIR");
626 return sd_bus_default_user(_bus);
628 ee = bus_address_escape(e);
632 r = sd_bus_new(&bus);
636 bus->address = strjoin("unix:path=", ee, "/systemd/private");
640 r = sd_bus_start(bus);
642 return sd_bus_default_user(_bus);
644 r = bus_check_peercred(bus);
655 #define print_property(name, fmt, ...) \
658 printf(fmt "\n", __VA_ARGS__); \
660 printf("%s=" fmt "\n", name, __VA_ARGS__); \
663 int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
665 const char *contents;
671 r = sd_bus_message_peek_type(m, &type, &contents);
677 case SD_BUS_TYPE_STRING: {
680 r = sd_bus_message_read_basic(m, type, &s);
684 if (all || !isempty(s)) {
687 /* This property has a single value, so we need to take
688 * care not to print a new line, everything else is OK. */
689 good = !strchr(s, '\n');
690 print_property(name, "%s", good ? s : "[unprintable]");
696 case SD_BUS_TYPE_BOOLEAN: {
699 r = sd_bus_message_read_basic(m, type, &b);
703 print_property(name, "%s", yes_no(b));
708 case SD_BUS_TYPE_UINT64: {
711 r = sd_bus_message_read_basic(m, type, &u);
715 /* Yes, heuristics! But we can change this check
716 * should it turn out to not be sufficient */
718 if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) {
719 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
721 t = format_timestamp(timestamp, sizeof(timestamp), u);
723 print_property(name, "%s", strempty(t));
725 } else if (strstr(name, "USec")) {
726 char timespan[FORMAT_TIMESPAN_MAX];
728 print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
729 } else if (streq(name, "RestrictNamespaces")) {
730 _cleanup_free_ char *s = NULL;
733 if ((u & NAMESPACE_FLAGS_ALL) == 0)
735 else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
738 r = namespace_flag_to_string_many(u, &s);
745 print_property(name, "%s", result);
747 } else if (streq(name, "MountFlags")) {
750 result = mount_propagation_flags_to_string(u);
754 print_property(name, "%s", result);
756 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
757 _cleanup_free_ char *s = NULL;
759 r = capability_set_to_string_alloc(u, &s);
763 print_property(name, "%s", s);
765 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
766 (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
767 (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
768 (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
769 (endswith(name, "NSec") && u == (uint64_t) -1))
771 print_property(name, "%s", "[not set]");
773 else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
774 (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
775 (startswith(name, "Limit") && u == (uint64_t) -1) ||
776 (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
778 print_property(name, "%s", "infinity");
780 print_property(name, "%"PRIu64, u);
785 case SD_BUS_TYPE_INT64: {
788 r = sd_bus_message_read_basic(m, type, &i);
792 print_property(name, "%"PRIi64, i);
797 case SD_BUS_TYPE_UINT32: {
800 r = sd_bus_message_read_basic(m, type, &u);
804 if (strstr(name, "UMask") || strstr(name, "Mode"))
805 print_property(name, "%04o", u);
806 else if (streq(name, "UID")) {
807 if (u == UID_INVALID)
808 print_property(name, "%s", "[not set]");
810 print_property(name, "%"PRIu32, u);
811 } else if (streq(name, "GID")) {
812 if (u == GID_INVALID)
813 print_property(name, "%s", "[not set]");
815 print_property(name, "%"PRIu32, u);
817 print_property(name, "%"PRIu32, u);
822 case SD_BUS_TYPE_INT32: {
825 r = sd_bus_message_read_basic(m, type, &i);
829 print_property(name, "%"PRIi32, i);
833 case SD_BUS_TYPE_DOUBLE: {
836 r = sd_bus_message_read_basic(m, type, &d);
840 print_property(name, "%g", d);
844 case SD_BUS_TYPE_ARRAY:
845 if (streq(contents, "s")) {
849 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
853 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
859 /* This property has multiple space-separated values, so
860 * neither spaces not newlines can be allowed in a value. */
861 good = str[strcspn(str, " \n")] == '\0';
863 printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
870 if (first && all && !value)
875 r = sd_bus_message_exit_container(m);
881 } else if (streq(contents, "y")) {
885 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
895 for (i = 0; i < n; i++)
896 printf("%02x", u[i]);
903 } else if (streq(contents, "u")) {
907 r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
917 for (i = 0; i < n; i++)
918 printf("%08x", u[i]);
932 int bus_message_print_all_properties(
934 bus_message_print_t func,
938 Set **found_properties) {
944 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
948 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
950 const char *contents;
952 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
956 if (found_properties) {
957 r = set_ensure_allocated(found_properties, &string_hash_ops);
961 r = set_put(*found_properties, name);
962 if (r < 0 && r != EEXIST)
966 if (!filter || strv_find(filter, name)) {
967 r = sd_bus_message_peek_type(m, NULL, &contents);
971 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
976 r = func(name, m, value, all);
978 r = bus_print_property(name, m, value, all);
983 printf("%s=[unprintable]\n", name);
984 /* skip what we didn't read */
985 r = sd_bus_message_skip(m, contents);
990 r = sd_bus_message_exit_container(m);
994 r = sd_bus_message_skip(m, "v");
999 r = sd_bus_message_exit_container(m);
1006 r = sd_bus_message_exit_container(m);
1013 int bus_print_all_properties(
1017 bus_message_print_t func,
1021 Set **found_properties) {
1023 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1024 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1030 r = sd_bus_call_method(bus,
1033 "org.freedesktop.DBus.Properties",
1041 return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
1044 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1045 sd_id128_t *p = userdata;
1050 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1057 memcpy((*p).bytes, v, n);
1064 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
1068 r = sd_bus_message_peek_type(m, &type, NULL);
1074 case SD_BUS_TYPE_STRING: {
1075 const char **p = userdata;
1078 r = sd_bus_message_read_basic(m, type, &s);
1085 if (flags & BUS_MAP_STRDUP)
1086 return free_and_strdup((char **) userdata, s);
1092 case SD_BUS_TYPE_ARRAY: {
1093 _cleanup_strv_free_ char **l = NULL;
1094 char ***p = userdata;
1096 r = bus_message_read_strv_extend(m, &l);
1105 case SD_BUS_TYPE_BOOLEAN: {
1108 r = sd_bus_message_read_basic(m, type, &b);
1112 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
1113 * (bool*) userdata = !!b;
1115 * (int*) userdata = b;
1120 case SD_BUS_TYPE_INT32:
1121 case SD_BUS_TYPE_UINT32: {
1122 uint32_t u, *p = userdata;
1124 r = sd_bus_message_read_basic(m, type, &u);
1132 case SD_BUS_TYPE_INT64:
1133 case SD_BUS_TYPE_UINT64: {
1134 uint64_t t, *p = userdata;
1136 r = sd_bus_message_read_basic(m, type, &t);
1144 case SD_BUS_TYPE_DOUBLE: {
1145 double d, *p = userdata;
1147 r = sd_bus_message_read_basic(m, type, &d);
1158 int bus_message_map_all_properties(
1160 const struct bus_properties_map *map,
1162 sd_bus_error *error,
1170 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1174 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1175 const struct bus_properties_map *prop;
1177 const char *contents;
1181 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1185 for (i = 0, prop = NULL; map[i].member; i++)
1186 if (streq(map[i].member, member)) {
1192 r = sd_bus_message_peek_type(m, NULL, &contents);
1196 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1200 v = (uint8_t *)userdata + prop->offset;
1202 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
1204 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
1208 r = sd_bus_message_exit_container(m);
1212 r = sd_bus_message_skip(m, "v");
1217 r = sd_bus_message_exit_container(m);
1224 return sd_bus_message_exit_container(m);
1227 #if 0 /// UNNEEDED by elogind
1228 int bus_message_map_properties_changed(
1230 const struct bus_properties_map *map,
1232 sd_bus_error *error,
1236 int r, invalidated, i;
1241 r = bus_message_map_all_properties(m, map, flags, error, userdata);
1245 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1250 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1251 for (i = 0; map[i].member; i++)
1252 if (streq(map[i].member, member)) {
1259 r = sd_bus_message_exit_container(m);
1267 int bus_map_all_properties(
1269 const char *destination,
1271 const struct bus_properties_map *map,
1273 sd_bus_error *error,
1274 sd_bus_message **reply,
1277 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1281 assert(destination);
1284 assert(reply || (flags & BUS_MAP_STRDUP));
1286 r = sd_bus_call_method(
1290 "org.freedesktop.DBus.Properties",
1298 r = bus_message_map_all_properties(m, map, flags, error, userdata);
1303 *reply = sd_bus_message_ref(m);
1308 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
1309 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1312 assert(transport >= 0);
1313 assert(transport < _BUS_TRANSPORT_MAX);
1316 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1317 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1319 switch (transport) {
1321 case BUS_TRANSPORT_LOCAL:
1322 #if 0 /// elogind does not support a user bus
1324 r = sd_bus_default_user(&bus);
1327 r = sd_bus_default_system(&bus);
1331 case BUS_TRANSPORT_REMOTE:
1332 r = sd_bus_open_system_remote(&bus, host);
1335 case BUS_TRANSPORT_MACHINE:
1336 r = sd_bus_open_system_machine(&bus, host);
1340 assert_not_reached("Hmm, unknown transport type.");
1345 r = sd_bus_set_exit_on_disconnect(bus, true);
1355 #if 0 /// UNNEEDED by elogind
1356 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1359 assert(transport >= 0);
1360 assert(transport < _BUS_TRANSPORT_MAX);
1363 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1364 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1366 switch (transport) {
1368 case BUS_TRANSPORT_LOCAL:
1370 r = bus_connect_user_systemd(bus);
1372 r = bus_connect_system_systemd(bus);
1376 case BUS_TRANSPORT_REMOTE:
1377 r = sd_bus_open_system_remote(bus, host);
1380 case BUS_TRANSPORT_MACHINE:
1381 r = sd_bus_open_system_machine(bus, host);
1385 assert_not_reached("Hmm, unknown transport type.");
1392 int bus_property_get_bool(
1395 const char *interface,
1396 const char *property,
1397 sd_bus_message *reply,
1399 sd_bus_error *error) {
1401 int b = *(bool*) userdata;
1403 return sd_bus_message_append_basic(reply, 'b', &b);
1406 int bus_property_set_bool(
1409 const char *interface,
1410 const char *property,
1411 sd_bus_message *value,
1413 sd_bus_error *error) {
1417 r = sd_bus_message_read(value, "b", &b);
1421 *(bool *) userdata = !!b;
1425 #if 0 /// UNNEEDED by elogind
1426 int bus_property_get_id128(
1429 const char *interface,
1430 const char *property,
1431 sd_bus_message *reply,
1433 sd_bus_error *error) {
1435 sd_id128_t *id = userdata;
1437 if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
1438 return sd_bus_message_append(reply, "ay", 0);
1440 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
1444 #if __SIZEOF_SIZE_T__ != 8
1445 int bus_property_get_size(
1448 const char *interface,
1449 const char *property,
1450 sd_bus_message *reply,
1452 sd_bus_error *error) {
1454 uint64_t sz = *(size_t*) userdata;
1456 return sd_bus_message_append_basic(reply, 't', &sz);
1460 #if __SIZEOF_LONG__ != 8
1461 int bus_property_get_long(
1464 const char *interface,
1465 const char *property,
1466 sd_bus_message *reply,
1468 sd_bus_error *error) {
1470 int64_t l = *(long*) userdata;
1472 return sd_bus_message_append_basic(reply, 'x', &l);
1475 int bus_property_get_ulong(
1478 const char *interface,
1479 const char *property,
1480 sd_bus_message *reply,
1482 sd_bus_error *error) {
1484 uint64_t ul = *(unsigned long*) userdata;
1486 return sd_bus_message_append_basic(reply, 't', &ul);
1490 int bus_log_parse_error(int r) {
1491 return log_error_errno(r, "Failed to parse bus message: %m");
1494 #if 0 /// UNNEEDED by elogind
1495 int bus_log_create_error(int r) {
1496 return log_error_errno(r, "Failed to create bus message: %m");
1500 #if 0 /// UNNEEDED by elogind
1502 * bus_path_encode_unique() - encode unique object path
1503 * @b: bus connection or NULL
1504 * @prefix: object path prefix
1505 * @sender_id: unique-name of client, or NULL
1506 * @external_id: external ID to be chosen by client, or NULL
1507 * @ret_path: storage for encoded object path pointer
1509 * Whenever we provide a bus API that allows clients to create and manage
1510 * server-side objects, we need to provide a unique name for these objects. If
1511 * we let the server choose the name, we suffer from a race condition: If a
1512 * client creates an object asynchronously, it cannot destroy that object until
1513 * it received the method reply. It cannot know the name of the new object,
1514 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1516 * Therefore, many APIs allow the client to choose the unique name for newly
1517 * created objects. There're two problems to solve, though:
1518 * 1) Object names are usually defined via dbus object paths, which are
1519 * usually globally namespaced. Therefore, multiple clients must be able
1520 * to choose unique object names without interference.
1521 * 2) If multiple libraries share the same bus connection, they must be
1522 * able to choose unique object names without interference.
1523 * The first problem is solved easily by prefixing a name with the
1524 * unique-bus-name of a connection. The server side must enforce this and
1525 * reject any other name. The second problem is solved by providing unique
1526 * suffixes from within sd-bus.
1528 * This helper allows clients to create unique object-paths. It uses the
1529 * template '/prefix/sender_id/external_id' and returns the new path in
1530 * @ret_path (must be freed by the caller).
1531 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1532 * NULL, this function allocates a unique suffix via @b (by requesting a new
1533 * cookie). If both @sender_id and @external_id are given, @b can be passed as
1536 * Returns: 0 on success, negative error code on failure.
1538 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1539 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1540 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1543 assert_return(b || (sender_id && external_id), -EINVAL);
1544 assert_return(object_path_is_valid(prefix), -EINVAL);
1545 assert_return(ret_path, -EINVAL);
1548 r = sd_bus_get_unique_name(b, &sender_id);
1554 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1555 external_id = external_buf;
1558 sender_label = bus_label_escape(sender_id);
1562 external_label = bus_label_escape(external_id);
1563 if (!external_label)
1566 p = strjoin(prefix, "/", sender_label, "/", external_label);
1575 * bus_path_decode_unique() - decode unique object path
1576 * @path: object path to decode
1577 * @prefix: object path prefix
1578 * @ret_sender: output parameter for sender-id label
1579 * @ret_external: output parameter for external-id label
1581 * This does the reverse of bus_path_encode_unique() (see its description for
1582 * details). Both trailing labels, sender-id and external-id, are unescaped and
1583 * returned in the given output parameters (the caller must free them).
1585 * Note that this function returns 0 if the path does not match the template
1586 * (see bus_path_encode_unique()), 1 if it matched.
1588 * Returns: Negative error code on failure, 0 if the given object path does not
1589 * match the template (return parameters are set to NULL), 1 if it was
1590 * parsed successfully (return parameters contain allocated labels).
1592 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1594 char *sender, *external;
1596 assert(object_path_is_valid(path));
1597 assert(object_path_is_valid(prefix));
1599 assert(ret_external);
1601 p = object_path_startswith(path, prefix);
1604 *ret_external = NULL;
1611 *ret_external = NULL;
1615 sender = bus_label_unescape_n(p, q - p);
1616 external = bus_label_unescape(q + 1);
1617 if (!sender || !external) {
1623 *ret_sender = sender;
1624 *ret_external = external;
1629 #if 0 /// UNNEEDED by elogind
1630 int bus_property_get_rlimit(
1633 const char *interface,
1634 const char *property,
1635 sd_bus_message *reply,
1637 sd_bus_error *error) {
1642 const char *is_soft;
1648 is_soft = endswith(property, "Soft");
1649 rl = *(struct rlimit**) userdata;
1651 x = is_soft ? rl->rlim_cur : rl->rlim_max;
1653 struct rlimit buf = {};
1657 s = is_soft ? strndupa(property, is_soft - property) : property;
1659 z = rlimit_from_string(strstr(s, "Limit"));
1663 x = is_soft ? buf.rlim_cur : buf.rlim_max;
1666 /* rlim_t might have different sizes, let's map
1667 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1669 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
1671 return sd_bus_message_append(reply, "t", u);
1674 int bus_track_add_name_many(sd_bus_track *t, char **l) {
1680 /* Continues adding after failure, and returns the first failure. */
1682 STRV_FOREACH(i, l) {
1685 k = sd_bus_track_add_name(t, *i);
1686 if (k < 0 && r >= 0)
1694 int bus_open_system_watch_bind(sd_bus **ret) {
1695 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1701 /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1703 r = sd_bus_new(&bus);
1707 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1709 e = DEFAULT_SYSTEM_BUS_ADDRESS;
1711 r = sd_bus_set_address(bus, e);
1715 r = sd_bus_set_bus_client(bus, true);
1719 r = sd_bus_set_trusted(bus, true);
1723 r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
1727 r = sd_bus_set_watch_bind(bus, true);
1731 r = sd_bus_set_connected_signal(bus, true);
1735 r = sd_bus_start(bus);