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>
25 #include "sd-daemon.h"
28 #include "alloc-util.h"
29 #include "bus-error.h"
30 #include "bus-internal.h"
31 #include "bus-label.h"
32 #include "bus-message.h"
34 #include "cgroup-util.h"
36 //#include "env-util.h"
41 #include "parse-util.h"
42 #include "path-util.h"
43 #include "proc-cmdline.h"
44 #include "process-util.h"
45 //#include "rlimit-util.h"
47 #include "signal-util.h"
48 #include "stdio-util.h"
49 #include "string-util.h"
51 #include "syslog-util.h"
52 #include "unit-name.h"
53 #include "user-util.h"
57 /// 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) {
72 _cleanup_free_ char *match = NULL;
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',"
97 "arg2=''", name, unique);
101 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
105 r = sd_bus_release_name(bus, name);
112 int bus_event_loop_with_idle(
117 check_idle_t check_idle,
119 bool exiting = false;
129 r = sd_event_get_state(e);
132 if (r == SD_EVENT_FINISHED)
136 idle = check_idle(userdata);
140 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
144 if (r == 0 && !exiting && idle) {
146 r = sd_bus_try_close(bus);
150 /* Fallback for dbus1 connections: we
151 * unregister the name and wait for the
152 * response to come through for it */
153 if (r == -EOPNOTSUPP) {
155 /* Inform the service manager that we
156 * are going down, so that it will
157 * queue all further start requests,
158 * instead of assuming we are already
160 sd_notify(false, "STOPPING=1");
162 r = bus_async_unregister_and_exit(e, bus, name);
178 r = sd_event_get_exit_code(e, &code);
186 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
187 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
188 int r, has_owner = 0;
193 r = sd_bus_call_method(c,
194 "org.freedesktop.DBus",
195 "/org/freedesktop/dbus",
196 "org.freedesktop.DBus",
205 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
207 return sd_bus_error_set_errno(error, r);
212 static int check_good_user(sd_bus_message *m, uid_t good_user) {
213 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
219 if (good_user == UID_INVALID)
222 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
226 /* Don't trust augmented credentials for authorization */
227 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
229 r = sd_bus_creds_get_euid(creds, &sender_uid);
233 return sender_uid == good_user;
237 sd_bus_message *call,
240 const char **details,
250 /* Tests non-interactively! */
252 r = check_good_user(call, good_user);
256 r = sd_bus_query_sender_privilege(call, capability);
263 _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
264 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
265 int authorized = false, challenge = false;
266 const char *sender, **k, **v;
268 sender = sd_bus_message_get_sender(call);
272 r = sd_bus_message_new_method_call(
275 "org.freedesktop.PolicyKit1",
276 "/org/freedesktop/PolicyKit1/Authority",
277 "org.freedesktop.PolicyKit1.Authority",
278 "CheckAuthorization");
282 r = sd_bus_message_append(
285 "system-bus-name", 1, "name", "s", sender,
290 r = sd_bus_message_open_container(request, 'a', "{ss}");
294 STRV_FOREACH_PAIR(k, v, details) {
295 r = sd_bus_message_append(request, "{ss}", *k, *v);
300 r = sd_bus_message_close_container(request);
304 r = sd_bus_message_append(request, "us", 0, NULL);
308 r = sd_bus_call(call->bus, request, 0, e, &reply);
310 /* Treat no PK available as access denied */
311 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
312 sd_bus_error_free(e);
319 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
323 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
331 *_challenge = challenge;
342 typedef struct AsyncPolkitQuery {
343 sd_bus_message *request, *reply;
344 sd_bus_message_handler_t callback;
350 static void async_polkit_query_free(AsyncPolkitQuery *q) {
355 sd_bus_slot_unref(q->slot);
357 if (q->registry && q->request)
358 hashmap_remove(q->registry, q->request);
360 sd_bus_message_unref(q->request);
361 sd_bus_message_unref(q->reply);
366 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
367 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
368 AsyncPolkitQuery *q = userdata;
374 q->slot = sd_bus_slot_unref(q->slot);
375 q->reply = sd_bus_message_ref(reply);
377 r = sd_bus_message_rewind(q->request, true);
379 r = sd_bus_reply_method_errno(q->request, r, NULL);
383 r = q->callback(q->request, q->userdata, &error_buffer);
384 r = bus_maybe_reply_error(q->request, r, &error_buffer);
387 async_polkit_query_free(q);
394 int bus_verify_polkit_async(
395 sd_bus_message *call,
398 const char **details,
402 sd_bus_error *error) {
405 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
407 const char *sender, **k, **v;
408 sd_bus_message_handler_t callback;
418 r = check_good_user(call, good_user);
423 q = hashmap_get(*registry, call);
425 int authorized, challenge;
427 /* This is the second invocation of this function, and
428 * there's already a response from polkit, let's
432 if (sd_bus_message_is_method_error(q->reply, NULL)) {
433 const sd_bus_error *e;
435 /* Copy error from polkit reply */
436 e = sd_bus_message_get_error(q->reply);
437 sd_bus_error_copy(error, e);
439 /* Treat no PK available as access denied */
440 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
443 return -sd_bus_error_get_errno(e);
446 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
448 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
457 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
463 r = sd_bus_query_sender_privilege(call, capability);
470 if (sd_bus_get_current_message(call->bus) != call)
473 callback = sd_bus_get_current_handler(call->bus);
477 userdata = sd_bus_get_current_userdata(call->bus);
479 sender = sd_bus_message_get_sender(call);
483 c = sd_bus_message_get_allow_interactive_authorization(call);
489 r = hashmap_ensure_allocated(registry, NULL);
493 r = sd_bus_message_new_method_call(
496 "org.freedesktop.PolicyKit1",
497 "/org/freedesktop/PolicyKit1/Authority",
498 "org.freedesktop.PolicyKit1.Authority",
499 "CheckAuthorization");
503 r = sd_bus_message_append(
506 "system-bus-name", 1, "name", "s", sender,
511 r = sd_bus_message_open_container(pk, 'a', "{ss}");
515 STRV_FOREACH_PAIR(k, v, details) {
516 r = sd_bus_message_append(pk, "{ss}", *k, *v);
521 r = sd_bus_message_close_container(pk);
525 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
529 q = new0(AsyncPolkitQuery, 1);
533 q->request = sd_bus_message_ref(call);
534 q->callback = callback;
535 q->userdata = userdata;
537 r = hashmap_put(*registry, call, q);
539 async_polkit_query_free(q);
543 q->registry = *registry;
545 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
547 async_polkit_query_free(q);
557 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
561 while ((q = hashmap_steal_first(registry)))
562 async_polkit_query_free(q);
564 hashmap_free(registry);
568 /// UNNEEDED by elogind
570 int bus_check_peercred(sd_bus *c) {
577 fd = sd_bus_get_fd(c);
581 l = sizeof(struct ucred);
582 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
585 if (l != sizeof(struct ucred))
588 if (ucred.uid != 0 && ucred.uid != geteuid())
594 int bus_connect_system_systemd(sd_bus **_bus) {
595 _cleanup_bus_unref_ sd_bus *bus = NULL;
601 return sd_bus_default_system(_bus);
603 /* If we are root and kdbus is not available, then let's talk
604 * directly to the system instance, instead of going via the
607 r = sd_bus_new(&bus);
611 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
615 bus->bus_client = true;
617 r = sd_bus_start(bus);
624 bus = sd_bus_unref(bus);
626 r = sd_bus_new(&bus);
630 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
634 r = sd_bus_start(bus);
636 return sd_bus_default_system(_bus);
638 r = bus_check_peercred(bus);
648 int bus_connect_user_systemd(sd_bus **_bus) {
649 _cleanup_bus_unref_ sd_bus *bus = NULL;
650 _cleanup_free_ char *ee = NULL;
654 /* Try via kdbus first, and then directly */
658 r = sd_bus_new(&bus);
662 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
665 bus->bus_client = true;
667 r = sd_bus_start(bus);
674 bus = sd_bus_unref(bus);
676 e = secure_getenv("XDG_RUNTIME_DIR");
678 return sd_bus_default_user(_bus);
680 ee = bus_address_escape(e);
684 r = sd_bus_new(&bus);
688 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
692 r = sd_bus_start(bus);
694 return sd_bus_default_user(_bus);
696 r = bus_check_peercred(bus);
707 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
709 const char *contents;
715 r = sd_bus_message_peek_type(property, &type, &contents);
721 case SD_BUS_TYPE_STRING: {
724 r = sd_bus_message_read_basic(property, type, &s);
728 if (all || !isempty(s)) {
729 _cleanup_free_ char *escaped = NULL;
731 escaped = xescape(s, "\n");
735 printf("%s=%s\n", name, escaped);
741 case SD_BUS_TYPE_BOOLEAN: {
744 r = sd_bus_message_read_basic(property, type, &b);
748 printf("%s=%s\n", name, yes_no(b));
753 case SD_BUS_TYPE_UINT64: {
756 r = sd_bus_message_read_basic(property, type, &u);
760 /* Yes, heuristics! But we can change this check
761 * should it turn out to not be sufficient */
763 if (endswith(name, "Timestamp")) {
764 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
766 t = format_timestamp(timestamp, sizeof(timestamp), u);
768 printf("%s=%s\n", name, strempty(t));
770 } else if (strstr(name, "USec")) {
771 char timespan[FORMAT_TIMESPAN_MAX];
773 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
775 printf("%s=%llu\n", name, (unsigned long long) u);
780 case SD_BUS_TYPE_INT64: {
783 r = sd_bus_message_read_basic(property, type, &i);
787 printf("%s=%lld\n", name, (long long) i);
792 case SD_BUS_TYPE_UINT32: {
795 r = sd_bus_message_read_basic(property, type, &u);
799 if (strstr(name, "UMask") || strstr(name, "Mode"))
800 printf("%s=%04o\n", name, u);
802 printf("%s=%u\n", name, (unsigned) u);
807 case SD_BUS_TYPE_INT32: {
810 r = sd_bus_message_read_basic(property, type, &i);
814 printf("%s=%i\n", name, (int) i);
818 case SD_BUS_TYPE_DOUBLE: {
821 r = sd_bus_message_read_basic(property, type, &d);
825 printf("%s=%g\n", name, d);
829 case SD_BUS_TYPE_ARRAY:
830 if (streq(contents, "s")) {
834 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
838 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
839 _cleanup_free_ char *escaped = NULL;
844 escaped = xescape(str, "\n ");
848 printf("%s%s", first ? "" : " ", escaped);
860 r = sd_bus_message_exit_container(property);
866 } else if (streq(contents, "y")) {
870 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
879 for (i = 0; i < n; i++)
880 printf("%02x", u[i]);
887 } else if (streq(contents, "u")) {
891 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
900 for (i = 0; i < n; i++)
901 printf("%08x", u[i]);
915 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
916 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
917 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
923 r = sd_bus_call_method(bus,
926 "org.freedesktop.DBus.Properties",
934 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
938 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
940 const char *contents;
942 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
946 if (!filter || strv_find(filter, name)) {
947 r = sd_bus_message_peek_type(reply, NULL, &contents);
951 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
955 r = bus_print_property(name, reply, all);
960 printf("%s=[unprintable]\n", name);
961 /* skip what we didn't read */
962 r = sd_bus_message_skip(reply, contents);
967 r = sd_bus_message_exit_container(reply);
971 r = sd_bus_message_skip(reply, "v");
976 r = sd_bus_message_exit_container(reply);
983 r = sd_bus_message_exit_container(reply);
990 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
991 sd_id128_t *p = userdata;
996 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1003 memcpy((*p).bytes, v, n);
1010 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1014 r = sd_bus_message_peek_type(m, &type, NULL);
1019 case SD_BUS_TYPE_STRING: {
1021 char **p = userdata;
1023 r = sd_bus_message_read_basic(m, type, &s);
1030 r = free_and_strdup(p, s);
1034 case SD_BUS_TYPE_ARRAY: {
1035 _cleanup_strv_free_ char **l = NULL;
1036 char ***p = userdata;
1038 r = bus_message_read_strv_extend(m, &l);
1049 case SD_BUS_TYPE_BOOLEAN: {
1053 r = sd_bus_message_read_basic(m, type, &b);
1062 case SD_BUS_TYPE_UINT32: {
1064 uint32_t *p = userdata;
1066 r = sd_bus_message_read_basic(m, type, &u);
1075 case SD_BUS_TYPE_UINT64: {
1077 uint64_t *p = userdata;
1079 r = sd_bus_message_read_basic(m, type, &t);
1095 int bus_message_map_all_properties(
1097 const struct bus_properties_map *map,
1100 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1106 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1110 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1111 const struct bus_properties_map *prop;
1113 const char *contents;
1117 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1121 for (i = 0, prop = NULL; map[i].member; i++)
1122 if (streq(map[i].member, member)) {
1128 r = sd_bus_message_peek_type(m, NULL, &contents);
1132 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1136 v = (uint8_t *)userdata + prop->offset;
1138 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1140 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1144 r = sd_bus_message_exit_container(m);
1148 r = sd_bus_message_skip(m, "v");
1153 r = sd_bus_message_exit_container(m);
1160 return sd_bus_message_exit_container(m);
1163 /// UNNEEDED by elogind
1165 int bus_message_map_properties_changed(
1167 const struct bus_properties_map *map,
1171 int r, invalidated, i;
1176 r = bus_message_map_all_properties(m, map, userdata);
1180 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1185 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1186 for (i = 0; map[i].member; i++)
1187 if (streq(map[i].member, member)) {
1194 r = sd_bus_message_exit_container(m);
1202 int bus_map_all_properties(
1204 const char *destination,
1206 const struct bus_properties_map *map,
1209 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1210 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1214 assert(destination);
1218 r = sd_bus_call_method(
1222 "org.freedesktop.DBus.Properties",
1230 return bus_message_map_all_properties(m, map, userdata);
1233 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1236 assert(transport >= 0);
1237 assert(transport < _BUS_TRANSPORT_MAX);
1240 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1241 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1243 switch (transport) {
1245 case BUS_TRANSPORT_LOCAL:
1246 /// elogind does not support a user bus
1249 r = sd_bus_default_user(bus);
1252 r = sd_bus_default_system(bus);
1256 case BUS_TRANSPORT_REMOTE:
1257 r = sd_bus_open_system_remote(bus, host);
1260 case BUS_TRANSPORT_MACHINE:
1261 r = sd_bus_open_system_machine(bus, host);
1265 assert_not_reached("Hmm, unknown transport type.");
1271 /// UNNEEDED by elogind
1273 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1276 assert(transport >= 0);
1277 assert(transport < _BUS_TRANSPORT_MAX);
1280 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1281 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1283 switch (transport) {
1285 case BUS_TRANSPORT_LOCAL:
1287 r = bus_connect_user_systemd(bus);
1289 r = bus_connect_system_systemd(bus);
1293 case BUS_TRANSPORT_REMOTE:
1294 r = sd_bus_open_system_remote(bus, host);
1297 case BUS_TRANSPORT_MACHINE:
1298 r = sd_bus_open_system_machine(bus, host);
1302 assert_not_reached("Hmm, unknown transport type.");
1309 int bus_property_get_bool(
1312 const char *interface,
1313 const char *property,
1314 sd_bus_message *reply,
1316 sd_bus_error *error) {
1318 int b = *(bool*) userdata;
1320 return sd_bus_message_append_basic(reply, 'b', &b);
1323 #if __SIZEOF_SIZE_T__ != 8
1324 int bus_property_get_size(
1327 const char *interface,
1328 const char *property,
1329 sd_bus_message *reply,
1331 sd_bus_error *error) {
1333 uint64_t sz = *(size_t*) userdata;
1335 return sd_bus_message_append_basic(reply, 't', &sz);
1339 #if __SIZEOF_LONG__ != 8
1340 int bus_property_get_long(
1343 const char *interface,
1344 const char *property,
1345 sd_bus_message *reply,
1347 sd_bus_error *error) {
1349 int64_t l = *(long*) userdata;
1351 return sd_bus_message_append_basic(reply, 'x', &l);
1354 int bus_property_get_ulong(
1357 const char *interface,
1358 const char *property,
1359 sd_bus_message *reply,
1361 sd_bus_error *error) {
1363 uint64_t ul = *(unsigned long*) userdata;
1365 return sd_bus_message_append_basic(reply, 't', &ul);
1369 int bus_log_parse_error(int r) {
1370 return log_error_errno(r, "Failed to parse bus message: %m");
1373 /// UNNEEDED by elogind
1375 int bus_log_create_error(int r) {
1376 return log_error_errno(r, "Failed to create bus message: %m");
1379 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1385 return sd_bus_message_read(
1400 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1401 const char *eq, *field;
1407 eq = strchr(assignment, '=');
1409 log_error("Not an assignment: %s", assignment);
1413 field = strndupa(assignment, eq - assignment);
1416 if (streq(field, "CPUQuota")) {
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_INFINITY);
1426 } else if (endswith(eq, "%")) {
1429 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1430 log_error("CPU quota '%s' invalid.", eq);
1434 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1436 return bus_log_create_error(r);
1438 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1440 log_error("CPU quota needs to be in percent.");
1445 return bus_log_create_error(r);
1448 } else if (streq(field, "EnvironmentFile")) {
1449 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
1453 r = sd_bus_message_append(m, "v", "a(sb)", 1,
1454 eq[0] == '-' ? eq + 1 : eq,
1461 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1463 return bus_log_create_error(r);
1465 if (STR_IN_SET(field,
1466 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1467 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1468 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1469 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
1470 "SyslogLevelPrefix", "Delegate")) {
1472 r = parse_boolean(eq);
1474 log_error("Failed to parse boolean assignment %s.", assignment);
1478 r = sd_bus_message_append(m, "v", "b", r);
1480 } else if (streq(field, "MemoryLimit")) {
1483 if (isempty(eq) || streq(eq, "infinity"))
1484 bytes = (uint64_t) -1;
1486 r = parse_size(eq, 1024, &bytes);
1488 log_error("Failed to parse bytes specification %s", assignment);
1493 r = sd_bus_message_append(m, "v", "t", bytes);
1495 } else if (streq(field, "TasksMax")) {
1498 if (isempty(eq) || streq(eq, "infinity"))
1501 r = safe_atou64(eq, &n);
1503 log_error("Failed to parse maximum tasks specification %s", assignment);
1508 r = sd_bus_message_append(m, "v", "t", n);
1510 } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
1513 r = cg_cpu_shares_parse(eq, &u);
1515 log_error("Failed to parse %s value %s.", field, eq);
1519 r = sd_bus_message_append(m, "v", "t", u);
1521 } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
1524 r = cg_cpu_shares_parse(eq, &u);
1526 log_error("Failed to parse %s value %s.", field, eq);
1530 r = sd_bus_message_append(m, "v", "t", u);
1532 } else if (STR_IN_SET(field,
1533 "User", "Group", "DevicePolicy", "KillMode",
1534 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1535 "StandardInput", "StandardOutput", "StandardError",
1536 "Description", "Slice", "Type", "WorkingDirectory",
1537 "RootDirectory", "SyslogIdentifier", "ProtectSystem",
1539 r = sd_bus_message_append(m, "v", "s", eq);
1541 else if (streq(field, "SyslogLevel")) {
1544 level = log_level_from_string(eq);
1546 log_error("Failed to parse %s value %s.", field, eq);
1550 r = sd_bus_message_append(m, "v", "i", level);
1552 } else if (streq(field, "SyslogFacility")) {
1555 facility = log_facility_unshifted_from_string(eq);
1557 log_error("Failed to parse %s value %s.", field, eq);
1561 r = sd_bus_message_append(m, "v", "i", facility);
1563 } else if (streq(field, "DeviceAllow")) {
1566 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1568 const char *path, *rwm, *e;
1570 e = strchr(eq, ' ');
1572 path = strndupa(eq, e - eq);
1579 if (!path_startswith(path, "/dev")) {
1580 log_error("%s is not a device file in /dev.", path);
1584 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1587 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1590 r = sd_bus_message_append(m, "v", "a(st)", 0);
1592 const char *path, *bandwidth, *e;
1595 e = strchr(eq, ' ');
1597 path = strndupa(eq, e - eq);
1600 log_error("Failed to parse %s value %s.", field, eq);
1604 if (!path_startswith(path, "/dev")) {
1605 log_error("%s is not a device file in /dev.", path);
1609 r = parse_size(bandwidth, 1000, &bytes);
1611 log_error("Failed to parse byte value %s.", bandwidth);
1615 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1618 } else if (streq(field, "BlockIODeviceWeight")) {
1621 r = sd_bus_message_append(m, "v", "a(st)", 0);
1623 const char *path, *weight, *e;
1626 e = strchr(eq, ' ');
1628 path = strndupa(eq, e - eq);
1631 log_error("Failed to parse %s value %s.", field, eq);
1635 if (!path_startswith(path, "/dev")) {
1636 log_error("%s is not a device file in /dev.", path);
1640 r = safe_atou64(weight, &u);
1642 log_error("Failed to parse %s value %s.", field, weight);
1645 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1648 } else if (rlimit_from_string(field) >= 0) {
1651 if (streq(eq, "infinity"))
1654 r = safe_atou64(eq, &rl);
1656 log_error("Invalid resource limit: %s", eq);
1661 r = sd_bus_message_append(m, "v", "t", rl);
1663 } else if (streq(field, "Nice")) {
1666 r = safe_atoi32(eq, &i);
1668 log_error("Failed to parse %s value %s.", field, eq);
1672 r = sd_bus_message_append(m, "v", "i", i);
1674 } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
1677 r = sd_bus_message_open_container(m, 'v', "as");
1679 return bus_log_create_error(r);
1681 r = sd_bus_message_open_container(m, 'a', "s");
1683 return bus_log_create_error(r);
1688 _cleanup_free_ char *word = NULL;
1690 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
1692 log_error("Failed to parse Environment value %s", eq);
1698 if (streq(field, "Environment")) {
1699 if (!env_assignment_is_valid(word)) {
1700 log_error("Invalid environment assignment: %s", word);
1703 } else { /* PassEnvironment */
1704 if (!env_name_is_valid(word)) {
1705 log_error("Invalid environment variable name: %s", word);
1710 r = sd_bus_message_append_basic(m, 's', word);
1712 return bus_log_create_error(r);
1715 r = sd_bus_message_close_container(m);
1717 return bus_log_create_error(r);
1719 r = sd_bus_message_close_container(m);
1721 } else if (streq(field, "KillSignal")) {
1724 sig = signal_from_string_try_harder(eq);
1726 log_error("Failed to parse %s value %s.", field, eq);
1730 r = sd_bus_message_append(m, "v", "i", sig);
1732 } else if (streq(field, "AccuracySec")) {
1735 r = parse_sec(eq, &u);
1737 log_error("Failed to parse %s value %s", field, eq);
1741 r = sd_bus_message_append(m, "v", "t", u);
1742 } else if (streq(field, "TimerSlackNSec")) {
1745 r = parse_nsec(eq, &n);
1747 log_error("Failed to parse %s value %s", field, eq);
1751 r = sd_bus_message_append(m, "v", "t", n);
1752 } else if (streq(field, "OOMScoreAdjust")) {
1755 r = safe_atoi(eq, &oa);
1757 log_error("Failed to parse %s value %s", field, eq);
1761 if (!oom_score_adjust_is_valid(oa)) {
1762 log_error("OOM score adjust value out of range");
1766 r = sd_bus_message_append(m, "v", "i", oa);
1767 } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1770 r = sd_bus_message_open_container(m, 'v', "as");
1772 return bus_log_create_error(r);
1774 r = sd_bus_message_open_container(m, 'a', "s");
1776 return bus_log_create_error(r);
1781 _cleanup_free_ char *word = NULL;
1784 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1786 log_error("Failed to parse %s value %s", field, eq);
1792 if (!utf8_is_valid(word)) {
1793 log_error("Failed to parse %s value %s", field, eq);
1797 offset = word[0] == '-';
1798 if (!path_is_absolute(word + offset)) {
1799 log_error("Failed to parse %s value %s", field, eq);
1803 path_kill_slashes(word + offset);
1805 r = sd_bus_message_append_basic(m, 's', word);
1807 return bus_log_create_error(r);
1810 r = sd_bus_message_close_container(m);
1812 return bus_log_create_error(r);
1814 r = sd_bus_message_close_container(m);
1816 } else if (streq(field, "RuntimeDirectory")) {
1819 r = sd_bus_message_open_container(m, 'v', "as");
1821 return bus_log_create_error(r);
1823 r = sd_bus_message_open_container(m, 'a', "s");
1825 return bus_log_create_error(r);
1830 _cleanup_free_ char *word = NULL;
1832 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1834 return log_error_errno(r, "Failed to parse %s value %s", field, eq);
1839 r = sd_bus_message_append_basic(m, 's', word);
1841 return bus_log_create_error(r);
1844 r = sd_bus_message_close_container(m);
1846 return bus_log_create_error(r);
1848 r = sd_bus_message_close_container(m);
1851 log_error("Unknown assignment %s.", assignment);
1856 return bus_log_create_error(r);
1862 typedef struct BusWaitForJobs {
1869 sd_bus_slot *slot_job_removed;
1870 sd_bus_slot *slot_disconnected;
1873 /// UNNEEDED by elogind
1875 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1878 log_error("Warning! D-Bus connection terminated.");
1879 sd_bus_close(sd_bus_message_get_bus(m));
1884 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1885 const char *path, *unit, *result;
1886 BusWaitForJobs *d = userdata;
1894 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1896 bus_log_parse_error(r);
1900 found = set_remove(d->jobs, (char*) path);
1906 if (!isempty(result))
1907 d->result = strdup(result);
1910 d->name = strdup(unit);
1915 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1919 set_free_free(d->jobs);
1921 sd_bus_slot_unref(d->slot_disconnected);
1922 sd_bus_slot_unref(d->slot_job_removed);
1924 sd_bus_unref(d->bus);
1932 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1933 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1939 d = new0(BusWaitForJobs, 1);
1943 d->bus = sd_bus_ref(bus);
1945 /* When we are a bus client we match by sender. Direct
1946 * connections OTOH have no initialized sender field, and
1947 * hence we ignore the sender then */
1948 r = sd_bus_add_match(
1950 &d->slot_job_removed,
1953 "sender='org.freedesktop.systemd1',"
1954 "interface='org.freedesktop.systemd1.Manager',"
1955 "member='JobRemoved',"
1956 "path='/org/freedesktop/systemd1'" :
1958 "interface='org.freedesktop.systemd1.Manager',"
1959 "member='JobRemoved',"
1960 "path='/org/freedesktop/systemd1'",
1961 match_job_removed, d);
1965 r = sd_bus_add_match(
1967 &d->slot_disconnected,
1969 "sender='org.freedesktop.DBus.Local',"
1970 "interface='org.freedesktop.DBus.Local',"
1971 "member='Disconnected'",
1972 match_disconnected, d);
1982 static int bus_process_wait(sd_bus *bus) {
1986 r = sd_bus_process(bus, NULL);
1992 r = sd_bus_wait(bus, (uint64_t) -1);
1998 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1999 _cleanup_free_ char *dbus_path = NULL;
2005 dbus_path = unit_dbus_path_from_name(d->name);
2009 return sd_bus_get_property_string(d->bus,
2010 "org.freedesktop.systemd1",
2012 "org.freedesktop.systemd1.Service",
2018 static const struct {
2019 const char *result, *explanation;
2020 } explanations [] = {
2021 { "resources", "a configured resource limit was exceeded" },
2022 { "timeout", "a timeout was exceeded" },
2023 { "exit-code", "the control process exited with error code" },
2024 { "signal", "a fatal signal was delivered to the control process" },
2025 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
2026 { "watchdog", "the service failed to send watchdog ping" },
2027 { "start-limit", "start of the service was attempted too often" }
2030 static void log_job_error_with_service_result(const char* service, const char *result) {
2031 _cleanup_free_ char *service_shell_quoted = NULL;
2035 service_shell_quoted = shell_maybe_quote(service);
2037 if (!isempty(result)) {
2040 for (i = 0; i < ELEMENTSOF(explanations); ++i)
2041 if (streq(result, explanations[i].result))
2044 if (i < ELEMENTSOF(explanations)) {
2045 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
2047 explanations[i].explanation,
2048 strna(service_shell_quoted));
2054 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
2056 strna(service_shell_quoted));
2059 /* For some results maybe additional explanation is required */
2060 if (streq_ptr(result, "start-limit"))
2061 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
2062 strna(service_shell_quoted));
2065 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
2071 if (streq(d->result, "canceled"))
2072 log_error("Job for %s canceled.", strna(d->name));
2073 else if (streq(d->result, "timeout"))
2074 log_error("Job for %s timed out.", strna(d->name));
2075 else if (streq(d->result, "dependency"))
2076 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2077 else if (streq(d->result, "invalid"))
2078 log_error("Job for %s invalid.", strna(d->name));
2079 else if (streq(d->result, "assert"))
2080 log_error("Assertion failed on job for %s.", strna(d->name));
2081 else if (streq(d->result, "unsupported"))
2082 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2083 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2086 _cleanup_free_ char *result = NULL;
2088 q = bus_job_get_service_result(d, &result);
2090 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
2092 log_job_error_with_service_result(d->name, result);
2094 log_error("Job failed. See \"journalctl -xe\" for details.");
2098 if (streq(d->result, "canceled"))
2100 else if (streq(d->result, "timeout"))
2102 else if (streq(d->result, "dependency"))
2104 else if (streq(d->result, "invalid"))
2106 else if (streq(d->result, "assert"))
2108 else if (streq(d->result, "unsupported"))
2110 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2116 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
2121 while (!set_isempty(d->jobs)) {
2124 q = bus_process_wait(d->bus);
2126 return log_error_errno(q, "Failed to wait for response: %m");
2129 q = check_wait_response(d, quiet);
2130 /* Return the first error as it is most likely to be
2132 if (q < 0 && r == 0)
2135 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
2138 d->name = mfree(d->name);
2139 d->result = mfree(d->result);
2145 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
2150 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
2154 return set_put_strdup(d->jobs, path);
2157 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
2160 r = bus_wait_for_jobs_add(d, path);
2164 return bus_wait_for_jobs(d, quiet);
2167 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
2168 const char *type, *path, *source;
2171 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
2173 return bus_log_parse_error(r);
2175 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
2177 if (streq(type, "symlink"))
2178 log_info("Created symlink from %s to %s.", path, source);
2180 log_info("Removed symlink %s.", path);
2183 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
2188 return bus_log_parse_error(r);
2190 r = sd_bus_message_exit_container(m);
2192 return bus_log_parse_error(r);
2198 * bus_path_encode_unique() - encode unique object path
2199 * @b: bus connection or NULL
2200 * @prefix: object path prefix
2201 * @sender_id: unique-name of client, or NULL
2202 * @external_id: external ID to be chosen by client, or NULL
2203 * @ret_path: storage for encoded object path pointer
2205 * Whenever we provide a bus API that allows clients to create and manage
2206 * server-side objects, we need to provide a unique name for these objects. If
2207 * we let the server choose the name, we suffer from a race condition: If a
2208 * client creates an object asynchronously, it cannot destroy that object until
2209 * it received the method reply. It cannot know the name of the new object,
2210 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2212 * Therefore, many APIs allow the client to choose the unique name for newly
2213 * created objects. There're two problems to solve, though:
2214 * 1) Object names are usually defined via dbus object paths, which are
2215 * usually globally namespaced. Therefore, multiple clients must be able
2216 * to choose unique object names without interference.
2217 * 2) If multiple libraries share the same bus connection, they must be
2218 * able to choose unique object names without interference.
2219 * The first problem is solved easily by prefixing a name with the
2220 * unique-bus-name of a connection. The server side must enforce this and
2221 * reject any other name. The second problem is solved by providing unique
2222 * suffixes from within sd-bus.
2224 * This helper allows clients to create unique object-paths. It uses the
2225 * template '/prefix/sender_id/external_id' and returns the new path in
2226 * @ret_path (must be freed by the caller).
2227 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2228 * NULL, this function allocates a unique suffix via @b (by requesting a new
2229 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2232 * Returns: 0 on success, negative error code on failure.
2234 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2235 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2236 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2239 assert_return(b || (sender_id && external_id), -EINVAL);
2240 assert_return(object_path_is_valid(prefix), -EINVAL);
2241 assert_return(ret_path, -EINVAL);
2244 r = sd_bus_get_unique_name(b, &sender_id);
2250 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2251 external_id = external_buf;
2254 sender_label = bus_label_escape(sender_id);
2258 external_label = bus_label_escape(external_id);
2259 if (!external_label)
2262 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2271 * bus_path_decode_unique() - decode unique object path
2272 * @path: object path to decode
2273 * @prefix: object path prefix
2274 * @ret_sender: output parameter for sender-id label
2275 * @ret_external: output parameter for external-id label
2277 * This does the reverse of bus_path_encode_unique() (see its description for
2278 * details). Both trailing labels, sender-id and external-id, are unescaped and
2279 * returned in the given output parameters (the caller must free them).
2281 * Note that this function returns 0 if the path does not match the template
2282 * (see bus_path_encode_unique()), 1 if it matched.
2284 * Returns: Negative error code on failure, 0 if the given object path does not
2285 * match the template (return parameters are set to NULL), 1 if it was
2286 * parsed successfully (return parameters contain allocated labels).
2288 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2290 char *sender, *external;
2292 assert(object_path_is_valid(path));
2293 assert(object_path_is_valid(prefix));
2295 assert(ret_external);
2297 p = object_path_startswith(path, prefix);
2300 *ret_external = NULL;
2307 *ret_external = NULL;
2311 sender = bus_label_unescape_n(p, q - p);
2312 external = bus_label_unescape(q + 1);
2313 if (!sender || !external) {
2319 *ret_sender = sender;
2320 *ret_external = external;
2325 bool is_kdbus_wanted(void) {
2326 _cleanup_free_ char *value = NULL;
2328 const bool configured = true;
2330 const bool configured = false;
2335 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2338 r = get_proc_cmdline_key("kdbus=", &value);
2342 return parse_boolean(value) == 1;
2345 bool is_kdbus_available(void) {
2346 _cleanup_close_ int fd = -1;
2347 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2349 if (!is_kdbus_wanted())
2352 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2356 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2359 /// UNNEEDED by elogind
2361 int bus_property_get_rlimit(
2364 const char *interface,
2365 const char *property,
2366 sd_bus_message *reply,
2368 sd_bus_error *error) {
2378 rl = *(struct rlimit**) userdata;
2382 struct rlimit buf = {};
2385 z = rlimit_from_string(strstr(property, "Limit"));
2392 /* rlim_t might have different sizes, let's map
2393 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2395 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
2397 return sd_bus_message_append(reply, "t", u);