1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 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/>.
22 #include <sys/socket.h>
24 #include "sd-daemon.h"
30 #include "path-util.h"
33 #include "signal-util.h"
34 #include "unit-name.h"
37 #include "bus-error.h"
38 #include "bus-label.h"
39 #include "bus-message.h"
41 #include "bus-internal.h"
43 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
44 sd_event *e = userdata;
49 sd_bus_close(sd_bus_message_get_bus(m));
55 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
56 _cleanup_free_ char *match = NULL;
64 /* We unregister the name here and then wait for the
65 * NameOwnerChanged signal for this event to arrive before we
66 * quit. We do this in order to make sure that any queued
67 * requests are still processed before we really exit. */
69 r = sd_bus_get_unique_name(bus, &unique);
74 "sender='org.freedesktop.DBus',"
76 "interface='org.freedesktop.DBus',"
77 "member='NameOwnerChanged',"
78 "path='/org/freedesktop/DBus',"
81 "arg2=''", name, unique);
85 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
89 r = sd_bus_release_name(bus, name);
96 /// UNNEEDED by elogind
98 int bus_event_loop_with_idle(
103 check_idle_t check_idle,
105 bool exiting = false;
115 r = sd_event_get_state(e);
118 if (r == SD_EVENT_FINISHED)
122 idle = check_idle(userdata);
126 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
130 if (r == 0 && !exiting && idle) {
132 r = sd_bus_try_close(bus);
136 /* Fallback for dbus1 connections: we
137 * unregister the name and wait for the
138 * response to come through for it */
139 if (r == -EOPNOTSUPP) {
141 /* Inform the service manager that we
142 * are going down, so that it will
143 * queue all further start requests,
144 * instead of assuming we are already
146 sd_notify(false, "STOPPING=1");
148 r = bus_async_unregister_and_exit(e, bus, name);
164 r = sd_event_get_exit_code(e, &code);
172 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
173 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
174 int r, has_owner = 0;
179 r = sd_bus_call_method(c,
180 "org.freedesktop.DBus",
181 "/org/freedesktop/dbus",
182 "org.freedesktop.DBus",
191 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
193 return sd_bus_error_set_errno(error, r);
198 static int check_good_user(sd_bus_message *m, uid_t good_user) {
199 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
205 if (good_user == UID_INVALID)
208 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
212 /* Don't trust augmented credentials for authorization */
213 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
215 r = sd_bus_creds_get_euid(creds, &sender_uid);
219 return sender_uid == good_user;
223 sd_bus_message *call,
226 const char **details,
236 /* Tests non-interactively! */
238 r = check_good_user(call, good_user);
242 r = sd_bus_query_sender_privilege(call, capability);
249 _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
250 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
251 int authorized = false, challenge = false;
252 const char *sender, **k, **v;
254 sender = sd_bus_message_get_sender(call);
258 r = sd_bus_message_new_method_call(
261 "org.freedesktop.PolicyKit1",
262 "/org/freedesktop/PolicyKit1/Authority",
263 "org.freedesktop.PolicyKit1.Authority",
264 "CheckAuthorization");
268 r = sd_bus_message_append(
271 "system-bus-name", 1, "name", "s", sender,
276 r = sd_bus_message_open_container(request, 'a', "{ss}");
280 STRV_FOREACH_PAIR(k, v, details) {
281 r = sd_bus_message_append(request, "{ss}", *k, *v);
286 r = sd_bus_message_close_container(request);
290 r = sd_bus_message_append(request, "us", 0, NULL);
294 r = sd_bus_call(call->bus, request, 0, e, &reply);
296 /* Treat no PK available as access denied */
297 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
298 sd_bus_error_free(e);
305 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
309 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
317 *_challenge = challenge;
328 typedef struct AsyncPolkitQuery {
329 sd_bus_message *request, *reply;
330 sd_bus_message_handler_t callback;
336 static void async_polkit_query_free(AsyncPolkitQuery *q) {
341 sd_bus_slot_unref(q->slot);
343 if (q->registry && q->request)
344 hashmap_remove(q->registry, q->request);
346 sd_bus_message_unref(q->request);
347 sd_bus_message_unref(q->reply);
352 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
353 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
354 AsyncPolkitQuery *q = userdata;
360 q->slot = sd_bus_slot_unref(q->slot);
361 q->reply = sd_bus_message_ref(reply);
363 r = sd_bus_message_rewind(q->request, true);
365 r = sd_bus_reply_method_errno(q->request, r, NULL);
369 r = q->callback(q->request, q->userdata, &error_buffer);
370 r = bus_maybe_reply_error(q->request, r, &error_buffer);
373 async_polkit_query_free(q);
380 int bus_verify_polkit_async(
381 sd_bus_message *call,
384 const char **details,
388 sd_bus_error *error) {
391 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
393 const char *sender, **k, **v;
394 sd_bus_message_handler_t callback;
404 r = check_good_user(call, good_user);
409 q = hashmap_get(*registry, call);
411 int authorized, challenge;
413 /* This is the second invocation of this function, and
414 * there's already a response from polkit, let's
418 if (sd_bus_message_is_method_error(q->reply, NULL)) {
419 const sd_bus_error *e;
421 /* Copy error from polkit reply */
422 e = sd_bus_message_get_error(q->reply);
423 sd_bus_error_copy(error, e);
425 /* Treat no PK available as access denied */
426 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
429 return -sd_bus_error_get_errno(e);
432 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
434 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
443 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
449 r = sd_bus_query_sender_privilege(call, capability);
456 if (sd_bus_get_current_message(call->bus) != call)
459 callback = sd_bus_get_current_handler(call->bus);
463 userdata = sd_bus_get_current_userdata(call->bus);
465 sender = sd_bus_message_get_sender(call);
469 c = sd_bus_message_get_allow_interactive_authorization(call);
475 r = hashmap_ensure_allocated(registry, NULL);
479 r = sd_bus_message_new_method_call(
482 "org.freedesktop.PolicyKit1",
483 "/org/freedesktop/PolicyKit1/Authority",
484 "org.freedesktop.PolicyKit1.Authority",
485 "CheckAuthorization");
489 r = sd_bus_message_append(
492 "system-bus-name", 1, "name", "s", sender,
497 r = sd_bus_message_open_container(pk, 'a', "{ss}");
501 STRV_FOREACH_PAIR(k, v, details) {
502 r = sd_bus_message_append(pk, "{ss}", *k, *v);
507 r = sd_bus_message_close_container(pk);
511 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
515 q = new0(AsyncPolkitQuery, 1);
519 q->request = sd_bus_message_ref(call);
520 q->callback = callback;
521 q->userdata = userdata;
523 r = hashmap_put(*registry, call, q);
525 async_polkit_query_free(q);
529 q->registry = *registry;
531 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
533 async_polkit_query_free(q);
543 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
547 while ((q = hashmap_steal_first(registry)))
548 async_polkit_query_free(q);
550 hashmap_free(registry);
554 int bus_check_peercred(sd_bus *c) {
561 fd = sd_bus_get_fd(c);
565 l = sizeof(struct ucred);
566 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
569 if (l != sizeof(struct ucred))
572 if (ucred.uid != 0 && ucred.uid != geteuid())
578 int bus_open_system_systemd(sd_bus **_bus) {
579 _cleanup_bus_unref_ sd_bus *bus = NULL;
585 return sd_bus_open_system(_bus);
587 /* If we are root and kdbus is not available, then let's talk
588 * directly to the system instance, instead of going via the
591 r = sd_bus_new(&bus);
595 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
599 bus->bus_client = true;
601 r = sd_bus_start(bus);
608 bus = sd_bus_unref(bus);
610 r = sd_bus_new(&bus);
614 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
618 r = sd_bus_start(bus);
620 return sd_bus_open_system(_bus);
622 r = bus_check_peercred(bus);
632 /// UNNEEDED by elogind
634 int bus_open_user_systemd(sd_bus **_bus) {
635 _cleanup_bus_unref_ sd_bus *bus = NULL;
636 _cleanup_free_ char *ee = NULL;
640 /* Try via kdbus first, and then directly */
644 r = sd_bus_new(&bus);
648 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
651 bus->bus_client = true;
653 r = sd_bus_start(bus);
660 bus = sd_bus_unref(bus);
662 e = secure_getenv("XDG_RUNTIME_DIR");
664 return sd_bus_open_user(_bus);
666 ee = bus_address_escape(e);
670 r = sd_bus_new(&bus);
674 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
678 r = sd_bus_start(bus);
680 return sd_bus_open_user(_bus);
682 r = bus_check_peercred(bus);
693 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
695 const char *contents;
701 r = sd_bus_message_peek_type(property, &type, &contents);
707 case SD_BUS_TYPE_STRING: {
710 r = sd_bus_message_read_basic(property, type, &s);
714 if (all || !isempty(s)) {
715 _cleanup_free_ char *escaped = NULL;
717 escaped = xescape(s, "\n");
721 printf("%s=%s\n", name, escaped);
727 case SD_BUS_TYPE_BOOLEAN: {
730 r = sd_bus_message_read_basic(property, type, &b);
734 printf("%s=%s\n", name, yes_no(b));
739 case SD_BUS_TYPE_UINT64: {
742 r = sd_bus_message_read_basic(property, type, &u);
746 /* Yes, heuristics! But we can change this check
747 * should it turn out to not be sufficient */
749 if (endswith(name, "Timestamp")) {
750 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
752 t = format_timestamp(timestamp, sizeof(timestamp), u);
754 printf("%s=%s\n", name, strempty(t));
756 } else if (strstr(name, "USec")) {
757 char timespan[FORMAT_TIMESPAN_MAX];
759 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
761 printf("%s=%llu\n", name, (unsigned long long) u);
766 case SD_BUS_TYPE_INT64: {
769 r = sd_bus_message_read_basic(property, type, &i);
773 printf("%s=%lld\n", name, (long long) i);
778 case SD_BUS_TYPE_UINT32: {
781 r = sd_bus_message_read_basic(property, type, &u);
785 if (strstr(name, "UMask") || strstr(name, "Mode"))
786 printf("%s=%04o\n", name, u);
788 printf("%s=%u\n", name, (unsigned) u);
793 case SD_BUS_TYPE_INT32: {
796 r = sd_bus_message_read_basic(property, type, &i);
800 printf("%s=%i\n", name, (int) i);
804 case SD_BUS_TYPE_DOUBLE: {
807 r = sd_bus_message_read_basic(property, type, &d);
811 printf("%s=%g\n", name, d);
815 case SD_BUS_TYPE_ARRAY:
816 if (streq(contents, "s")) {
820 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
824 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
825 _cleanup_free_ char *escaped = NULL;
830 escaped = xescape(str, "\n ");
834 printf("%s%s", first ? "" : " ", escaped);
846 r = sd_bus_message_exit_container(property);
852 } else if (streq(contents, "y")) {
856 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
865 for (i = 0; i < n; i++)
866 printf("%02x", u[i]);
873 } else if (streq(contents, "u")) {
877 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
886 for (i = 0; i < n; i++)
887 printf("%08x", u[i]);
901 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
902 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
903 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
909 r = sd_bus_call_method(bus,
912 "org.freedesktop.DBus.Properties",
920 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
924 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
926 const char *contents;
928 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
932 if (!filter || strv_find(filter, name)) {
933 r = sd_bus_message_peek_type(reply, NULL, &contents);
937 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
941 r = bus_print_property(name, reply, all);
946 printf("%s=[unprintable]\n", name);
947 /* skip what we didn't read */
948 r = sd_bus_message_skip(reply, contents);
953 r = sd_bus_message_exit_container(reply);
957 r = sd_bus_message_skip(reply, "v");
962 r = sd_bus_message_exit_container(reply);
969 r = sd_bus_message_exit_container(reply);
976 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
977 sd_id128_t *p = userdata;
982 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
989 memcpy((*p).bytes, v, n);
996 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1000 r = sd_bus_message_peek_type(m, &type, NULL);
1005 case SD_BUS_TYPE_STRING: {
1007 char **p = userdata;
1009 r = sd_bus_message_read_basic(m, type, &s);
1016 r = free_and_strdup(p, s);
1020 case SD_BUS_TYPE_ARRAY: {
1021 _cleanup_strv_free_ char **l = NULL;
1022 char ***p = userdata;
1024 r = bus_message_read_strv_extend(m, &l);
1035 case SD_BUS_TYPE_BOOLEAN: {
1039 r = sd_bus_message_read_basic(m, type, &b);
1048 case SD_BUS_TYPE_UINT32: {
1050 uint32_t *p = userdata;
1052 r = sd_bus_message_read_basic(m, type, &u);
1061 case SD_BUS_TYPE_UINT64: {
1063 uint64_t *p = userdata;
1065 r = sd_bus_message_read_basic(m, type, &t);
1081 int bus_message_map_all_properties(
1083 const struct bus_properties_map *map,
1086 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1092 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1096 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1097 const struct bus_properties_map *prop;
1099 const char *contents;
1103 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1107 for (i = 0, prop = NULL; map[i].member; i++)
1108 if (streq(map[i].member, member)) {
1114 r = sd_bus_message_peek_type(m, NULL, &contents);
1118 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1122 v = (uint8_t *)userdata + prop->offset;
1124 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1126 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1130 r = sd_bus_message_exit_container(m);
1134 r = sd_bus_message_skip(m, "v");
1139 r = sd_bus_message_exit_container(m);
1146 return sd_bus_message_exit_container(m);
1149 /// UNNEEDED by elogind
1151 int bus_message_map_properties_changed(
1153 const struct bus_properties_map *map,
1157 int r, invalidated, i;
1162 r = bus_message_map_all_properties(m, map, userdata);
1166 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1171 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1172 for (i = 0; map[i].member; i++)
1173 if (streq(map[i].member, member)) {
1180 r = sd_bus_message_exit_container(m);
1188 int bus_map_all_properties(
1190 const char *destination,
1192 const struct bus_properties_map *map,
1195 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1196 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1200 assert(destination);
1204 r = sd_bus_call_method(
1208 "org.freedesktop.DBus.Properties",
1216 return bus_message_map_all_properties(m, map, userdata);
1219 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1222 assert(transport >= 0);
1223 assert(transport < _BUS_TRANSPORT_MAX);
1226 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1227 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1229 switch (transport) {
1231 case BUS_TRANSPORT_LOCAL:
1232 /// elogind does not support a user bus
1235 r = sd_bus_default_user(bus);
1238 r = sd_bus_default_system(bus);
1242 case BUS_TRANSPORT_REMOTE:
1243 r = sd_bus_open_system_remote(bus, host);
1246 case BUS_TRANSPORT_MACHINE:
1247 r = sd_bus_open_system_machine(bus, host);
1251 assert_not_reached("Hmm, unknown transport type.");
1257 /// UNNEEDED by elogind
1259 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1262 assert(transport >= 0);
1263 assert(transport < _BUS_TRANSPORT_MAX);
1266 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1267 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1269 switch (transport) {
1271 case BUS_TRANSPORT_LOCAL:
1273 r = bus_open_user_systemd(bus);
1275 r = bus_open_system_systemd(bus);
1279 case BUS_TRANSPORT_REMOTE:
1280 r = sd_bus_open_system_remote(bus, host);
1283 case BUS_TRANSPORT_MACHINE:
1284 r = sd_bus_open_system_machine(bus, host);
1288 assert_not_reached("Hmm, unknown transport type.");
1295 int bus_property_get_bool(
1298 const char *interface,
1299 const char *property,
1300 sd_bus_message *reply,
1302 sd_bus_error *error) {
1304 int b = *(bool*) userdata;
1306 return sd_bus_message_append_basic(reply, 'b', &b);
1309 #if __SIZEOF_SIZE_T__ != 8
1310 int bus_property_get_size(
1313 const char *interface,
1314 const char *property,
1315 sd_bus_message *reply,
1317 sd_bus_error *error) {
1319 uint64_t sz = *(size_t*) userdata;
1321 return sd_bus_message_append_basic(reply, 't', &sz);
1325 #if __SIZEOF_LONG__ != 8
1326 int bus_property_get_long(
1329 const char *interface,
1330 const char *property,
1331 sd_bus_message *reply,
1333 sd_bus_error *error) {
1335 int64_t l = *(long*) userdata;
1337 return sd_bus_message_append_basic(reply, 'x', &l);
1340 int bus_property_get_ulong(
1343 const char *interface,
1344 const char *property,
1345 sd_bus_message *reply,
1347 sd_bus_error *error) {
1349 uint64_t ul = *(unsigned long*) userdata;
1351 return sd_bus_message_append_basic(reply, 't', &ul);
1355 int bus_log_parse_error(int r) {
1356 return log_error_errno(r, "Failed to parse bus message: %m");
1359 int bus_log_create_error(int r) {
1360 return log_error_errno(r, "Failed to create bus message: %m");
1363 /// UNNEEDED by elogind
1365 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1371 return sd_bus_message_read(
1386 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1387 const char *eq, *field;
1393 eq = strchr(assignment, '=');
1395 log_error("Not an assignment: %s", assignment);
1399 field = strndupa(assignment, eq - assignment);
1402 if (streq(field, "CPUQuota")) {
1406 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1408 return bus_log_create_error(r);
1410 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1412 } else if (endswith(eq, "%")) {
1415 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1416 log_error("CPU quota '%s' invalid.", eq);
1420 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1422 return bus_log_create_error(r);
1424 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1426 log_error("CPU quota needs to be in percent.");
1431 return bus_log_create_error(r);
1436 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1438 return bus_log_create_error(r);
1440 if (STR_IN_SET(field,
1441 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1442 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1443 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit")) {
1445 r = parse_boolean(eq);
1447 log_error("Failed to parse boolean assignment %s.", assignment);
1451 r = sd_bus_message_append(m, "v", "b", r);
1453 } else if (streq(field, "MemoryLimit")) {
1456 r = parse_size(eq, 1024, &bytes);
1458 log_error("Failed to parse bytes specification %s", assignment);
1462 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1464 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1467 r = safe_atou64(eq, &u);
1469 log_error("Failed to parse %s value %s.", field, eq);
1473 r = sd_bus_message_append(m, "v", "t", u);
1475 } else if (STR_IN_SET(field,
1476 "User", "Group", "DevicePolicy", "KillMode",
1477 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1478 "StandardInput", "StandardOutput", "StandardError",
1479 "Description", "Slice", "Type"))
1480 r = sd_bus_message_append(m, "v", "s", eq);
1482 else if (streq(field, "DeviceAllow")) {
1485 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1487 const char *path, *rwm, *e;
1489 e = strchr(eq, ' ');
1491 path = strndupa(eq, e - eq);
1498 if (!path_startswith(path, "/dev")) {
1499 log_error("%s is not a device file in /dev.", path);
1503 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1506 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1509 r = sd_bus_message_append(m, "v", "a(st)", 0);
1511 const char *path, *bandwidth, *e;
1514 e = strchr(eq, ' ');
1516 path = strndupa(eq, e - eq);
1519 log_error("Failed to parse %s value %s.", field, eq);
1523 if (!path_startswith(path, "/dev")) {
1524 log_error("%s is not a device file in /dev.", path);
1528 r = parse_size(bandwidth, 1000, &bytes);
1530 log_error("Failed to parse byte value %s.", bandwidth);
1534 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1537 } else if (streq(field, "BlockIODeviceWeight")) {
1540 r = sd_bus_message_append(m, "v", "a(st)", 0);
1542 const char *path, *weight, *e;
1545 e = strchr(eq, ' ');
1547 path = strndupa(eq, e - eq);
1550 log_error("Failed to parse %s value %s.", field, eq);
1554 if (!path_startswith(path, "/dev")) {
1555 log_error("%s is not a device file in /dev.", path);
1559 r = safe_atou64(weight, &u);
1561 log_error("Failed to parse %s value %s.", field, weight);
1564 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1567 } else if (rlimit_from_string(field) >= 0) {
1570 if (streq(eq, "infinity"))
1573 r = safe_atou64(eq, &rl);
1575 log_error("Invalid resource limit: %s", eq);
1580 r = sd_bus_message_append(m, "v", "t", rl);
1582 } else if (streq(field, "Nice")) {
1585 r = safe_atoi32(eq, &i);
1587 log_error("Failed to parse %s value %s.", field, eq);
1591 r = sd_bus_message_append(m, "v", "i", i);
1593 } else if (streq(field, "Environment")) {
1595 r = sd_bus_message_append(m, "v", "as", 1, eq);
1597 } else if (streq(field, "KillSignal")) {
1600 sig = signal_from_string_try_harder(eq);
1602 log_error("Failed to parse %s value %s.", field, eq);
1606 r = sd_bus_message_append(m, "v", "i", sig);
1608 } else if (streq(field, "AccuracySec")) {
1611 r = parse_sec(eq, &u);
1613 log_error("Failed to parse %s value %s", field, eq);
1617 r = sd_bus_message_append(m, "v", "t", u);
1620 log_error("Unknown assignment %s.", assignment);
1625 return bus_log_create_error(r);
1631 typedef struct BusWaitForJobs {
1638 sd_bus_slot *slot_job_removed;
1639 sd_bus_slot *slot_disconnected;
1642 /// UNNEEDED by elogind
1644 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1647 log_error("Warning! D-Bus connection terminated.");
1648 sd_bus_close(sd_bus_message_get_bus(m));
1653 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1654 const char *path, *unit, *result;
1655 BusWaitForJobs *d = userdata;
1663 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1665 bus_log_parse_error(r);
1669 found = set_remove(d->jobs, (char*) path);
1675 if (!isempty(result))
1676 d->result = strdup(result);
1679 d->name = strdup(unit);
1685 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1689 set_free_free(d->jobs);
1691 sd_bus_slot_unref(d->slot_disconnected);
1692 sd_bus_slot_unref(d->slot_job_removed);
1694 sd_bus_unref(d->bus);
1702 /// UNNEEDED by elogind
1704 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1705 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1711 d = new0(BusWaitForJobs, 1);
1715 d->bus = sd_bus_ref(bus);
1717 /* When we are a bus client we match by sender. Direct
1718 * connections OTOH have no initialized sender field, and
1719 * hence we ignore the sender then */
1720 r = sd_bus_add_match(
1722 &d->slot_job_removed,
1725 "sender='org.freedesktop.systemd1',"
1726 "interface='org.freedesktop.systemd1.Manager',"
1727 "member='JobRemoved',"
1728 "path='/org/freedesktop/systemd1'" :
1730 "interface='org.freedesktop.systemd1.Manager',"
1731 "member='JobRemoved',"
1732 "path='/org/freedesktop/systemd1'",
1733 match_job_removed, d);
1737 r = sd_bus_add_match(
1739 &d->slot_disconnected,
1741 "sender='org.freedesktop.DBus.Local',"
1742 "interface='org.freedesktop.DBus.Local',"
1743 "member='Disconnected'",
1744 match_disconnected, d);
1755 static int bus_process_wait(sd_bus *bus) {
1759 r = sd_bus_process(bus, NULL);
1765 r = sd_bus_wait(bus, (uint64_t) -1);
1771 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1772 _cleanup_free_ char *dbus_path = NULL;
1778 dbus_path = unit_dbus_path_from_name(d->name);
1782 return sd_bus_get_property_string(d->bus,
1783 "org.freedesktop.systemd1",
1785 "org.freedesktop.systemd1.Service",
1791 static const struct {
1792 const char *result, *explanation;
1793 } explanations [] = {
1794 { "resources", "a configured resource limit was exceeded" },
1795 { "timeout", "a timeout was exceeded" },
1796 { "exit-code", "the control process exited with error code" },
1797 { "signal", "a fatal signal was delivered to the control process" },
1798 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
1799 { "watchdog", "the service failed to send watchdog ping" },
1800 { "start-limit", "start of the service was attempted too often" }
1803 static void log_job_error_with_service_result(const char* service, const char *result) {
1804 _cleanup_free_ char *service_shell_quoted = NULL;
1808 service_shell_quoted = shell_maybe_quote(service);
1810 if (!isempty(result)) {
1813 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1814 if (streq(result, explanations[i].result))
1817 if (i < ELEMENTSOF(explanations)) {
1818 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1820 explanations[i].explanation,
1821 strna(service_shell_quoted));
1827 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1829 strna(service_shell_quoted));
1832 /* For some results maybe additional explanation is required */
1833 if (streq_ptr(result, "start-limit"))
1834 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1835 strna(service_shell_quoted));
1838 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1844 if (streq(d->result, "canceled"))
1845 log_error("Job for %s canceled.", strna(d->name));
1846 else if (streq(d->result, "timeout"))
1847 log_error("Job for %s timed out.", strna(d->name));
1848 else if (streq(d->result, "dependency"))
1849 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1850 else if (streq(d->result, "invalid"))
1851 log_error("Job for %s invalid.", strna(d->name));
1852 else if (streq(d->result, "assert"))
1853 log_error("Assertion failed on job for %s.", strna(d->name));
1854 else if (streq(d->result, "unsupported"))
1855 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1856 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1859 _cleanup_free_ char *result = NULL;
1861 q = bus_job_get_service_result(d, &result);
1863 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1865 log_job_error_with_service_result(d->name, result);
1867 log_error("Job failed. See \"journalctl -xe\" for details.");
1871 if (streq(d->result, "canceled"))
1873 else if (streq(d->result, "timeout"))
1875 else if (streq(d->result, "dependency"))
1877 else if (streq(d->result, "invalid"))
1879 else if (streq(d->result, "assert"))
1881 else if (streq(d->result, "unsupported"))
1883 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1889 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1894 while (!set_isempty(d->jobs)) {
1897 q = bus_process_wait(d->bus);
1899 return log_error_errno(q, "Failed to wait for response: %m");
1902 q = check_wait_response(d, quiet);
1903 /* Return the first error as it is most likely to be
1905 if (q < 0 && r == 0)
1908 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1921 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1926 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1930 return set_put_strdup(d->jobs, path);
1933 /// UNNEEDED by elogind
1935 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
1936 const char *type, *path, *source;
1939 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1941 return bus_log_parse_error(r);
1943 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1945 if (streq(type, "symlink"))
1946 log_info("Created symlink from %s to %s.", path, source);
1948 log_info("Removed symlink %s.", path);
1951 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
1956 return bus_log_parse_error(r);
1958 r = sd_bus_message_exit_container(m);
1960 return bus_log_parse_error(r);
1967 * bus_path_encode_unique() - encode unique object path
1968 * @b: bus connection or NULL
1969 * @prefix: object path prefix
1970 * @sender_id: unique-name of client, or NULL
1971 * @external_id: external ID to be chosen by client, or NULL
1972 * @ret_path: storage for encoded object path pointer
1974 * Whenever we provide a bus API that allows clients to create and manage
1975 * server-side objects, we need to provide a unique name for these objects. If
1976 * we let the server choose the name, we suffer from a race condition: If a
1977 * client creates an object asynchronously, it cannot destroy that object until
1978 * it received the method reply. It cannot know the name of the new object,
1979 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1981 * Therefore, many APIs allow the client to choose the unique name for newly
1982 * created objects. There're two problems to solve, though:
1983 * 1) Object names are usually defined via dbus object paths, which are
1984 * usually globally namespaced. Therefore, multiple clients must be able
1985 * to choose unique object names without interference.
1986 * 2) If multiple libraries share the same bus connection, they must be
1987 * able to choose unique object names without interference.
1988 * The first problem is solved easily by prefixing a name with the
1989 * unique-bus-name of a connection. The server side must enforce this and
1990 * reject any other name. The second problem is solved by providing unique
1991 * suffixes from within sd-bus.
1993 * This helper allows clients to create unique object-paths. It uses the
1994 * template '/prefix/sender_id/external_id' and returns the new path in
1995 * @ret_path (must be freed by the caller).
1996 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1997 * NULL, this function allocates a unique suffix via @b (by requesting a new
1998 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2001 * Returns: 0 on success, negative error code on failure.
2003 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2004 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2005 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2008 assert_return(b || (sender_id && external_id), -EINVAL);
2009 assert_return(object_path_is_valid(prefix), -EINVAL);
2010 assert_return(ret_path, -EINVAL);
2013 r = sd_bus_get_unique_name(b, &sender_id);
2019 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2020 external_id = external_buf;
2023 sender_label = bus_label_escape(sender_id);
2027 external_label = bus_label_escape(external_id);
2028 if (!external_label)
2031 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2040 * bus_path_decode_unique() - decode unique object path
2041 * @path: object path to decode
2042 * @prefix: object path prefix
2043 * @ret_sender: output parameter for sender-id label
2044 * @ret_external: output parameter for external-id label
2046 * This does the reverse of bus_path_encode_unique() (see its description for
2047 * details). Both trailing labels, sender-id and external-id, are unescaped and
2048 * returned in the given output parameters (the caller must free them).
2050 * Note that this function returns 0 if the path does not match the template
2051 * (see bus_path_encode_unique()), 1 if it matched.
2053 * Returns: Negative error code on failure, 0 if the given object path does not
2054 * match the template (return parameters are set to NULL), 1 if it was
2055 * parsed successfully (return parameters contain allocated labels).
2057 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2059 char *sender, *external;
2061 assert(object_path_is_valid(path));
2062 assert(object_path_is_valid(prefix));
2064 assert(ret_external);
2066 p = object_path_startswith(path, prefix);
2069 *ret_external = NULL;
2076 *ret_external = NULL;
2080 sender = bus_label_unescape_n(p, q - p);
2081 external = bus_label_unescape(q + 1);
2082 if (!sender || !external) {
2088 *ret_sender = sender;
2089 *ret_external = external;
2093 bool is_kdbus_wanted(void) {
2094 _cleanup_free_ char *value = NULL;
2096 const bool configured = true;
2098 const bool configured = false;
2103 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2106 r = get_proc_cmdline_key("kdbus=", &value);
2110 return parse_boolean(value) == 1;
2113 bool is_kdbus_available(void) {
2114 _cleanup_close_ int fd = -1;
2115 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2117 if (!is_kdbus_wanted())
2120 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2124 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;