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 #if 0 /// UNNEEDED by elogind
58 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
59 sd_event *e = userdata;
64 sd_bus_close(sd_bus_message_get_bus(m));
70 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
71 _cleanup_free_ char *match = NULL;
79 /* We unregister the name here and then wait for the
80 * NameOwnerChanged signal for this event to arrive before we
81 * quit. We do this in order to make sure that any queued
82 * requests are still processed before we really exit. */
84 r = sd_bus_get_unique_name(bus, &unique);
89 "sender='org.freedesktop.DBus',"
91 "interface='org.freedesktop.DBus',"
92 "member='NameOwnerChanged',"
93 "path='/org/freedesktop/DBus',"
96 "arg2=''", name, unique);
100 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
104 r = sd_bus_release_name(bus, name);
111 int bus_event_loop_with_idle(
116 check_idle_t check_idle,
118 bool exiting = false;
128 r = sd_event_get_state(e);
131 if (r == SD_EVENT_FINISHED)
135 idle = check_idle(userdata);
139 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
143 if (r == 0 && !exiting && idle) {
145 r = sd_bus_try_close(bus);
149 /* Fallback for dbus1 connections: we
150 * unregister the name and wait for the
151 * response to come through for it */
152 if (r == -EOPNOTSUPP) {
154 /* Inform the service manager that we
155 * are going down, so that it will
156 * queue all further start requests,
157 * instead of assuming we are already
159 sd_notify(false, "STOPPING=1");
161 r = bus_async_unregister_and_exit(e, bus, name);
177 r = sd_event_get_exit_code(e, &code);
185 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
186 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
187 int r, has_owner = 0;
192 r = sd_bus_call_method(c,
193 "org.freedesktop.DBus",
194 "/org/freedesktop/dbus",
195 "org.freedesktop.DBus",
204 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
206 return sd_bus_error_set_errno(error, r);
211 static int check_good_user(sd_bus_message *m, uid_t good_user) {
212 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
218 if (good_user == UID_INVALID)
221 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
225 /* Don't trust augmented credentials for authorization */
226 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
228 r = sd_bus_creds_get_euid(creds, &sender_uid);
232 return sender_uid == good_user;
236 sd_bus_message *call,
239 const char **details,
249 /* Tests non-interactively! */
251 r = check_good_user(call, good_user);
255 r = sd_bus_query_sender_privilege(call, capability);
262 _cleanup_bus_message_unref_ sd_bus_message *request = NULL;
263 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
264 int authorized = false, challenge = false;
265 const char *sender, **k, **v;
267 sender = sd_bus_message_get_sender(call);
271 r = sd_bus_message_new_method_call(
274 "org.freedesktop.PolicyKit1",
275 "/org/freedesktop/PolicyKit1/Authority",
276 "org.freedesktop.PolicyKit1.Authority",
277 "CheckAuthorization");
281 r = sd_bus_message_append(
284 "system-bus-name", 1, "name", "s", sender,
289 r = sd_bus_message_open_container(request, 'a', "{ss}");
293 STRV_FOREACH_PAIR(k, v, details) {
294 r = sd_bus_message_append(request, "{ss}", *k, *v);
299 r = sd_bus_message_close_container(request);
303 r = sd_bus_message_append(request, "us", 0, NULL);
307 r = sd_bus_call(call->bus, request, 0, e, &reply);
309 /* Treat no PK available as access denied */
310 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
311 sd_bus_error_free(e);
318 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
322 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
330 *_challenge = challenge;
341 typedef struct AsyncPolkitQuery {
342 sd_bus_message *request, *reply;
343 sd_bus_message_handler_t callback;
349 static void async_polkit_query_free(AsyncPolkitQuery *q) {
354 sd_bus_slot_unref(q->slot);
356 if (q->registry && q->request)
357 hashmap_remove(q->registry, q->request);
359 sd_bus_message_unref(q->request);
360 sd_bus_message_unref(q->reply);
365 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
366 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
367 AsyncPolkitQuery *q = userdata;
373 q->slot = sd_bus_slot_unref(q->slot);
374 q->reply = sd_bus_message_ref(reply);
376 r = sd_bus_message_rewind(q->request, true);
378 r = sd_bus_reply_method_errno(q->request, r, NULL);
382 r = q->callback(q->request, q->userdata, &error_buffer);
383 r = bus_maybe_reply_error(q->request, r, &error_buffer);
386 async_polkit_query_free(q);
393 int bus_verify_polkit_async(
394 sd_bus_message *call,
397 const char **details,
401 sd_bus_error *error) {
404 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
406 const char *sender, **k, **v;
407 sd_bus_message_handler_t callback;
417 r = check_good_user(call, good_user);
422 q = hashmap_get(*registry, call);
424 int authorized, challenge;
426 /* This is the second invocation of this function, and
427 * there's already a response from polkit, let's
431 if (sd_bus_message_is_method_error(q->reply, NULL)) {
432 const sd_bus_error *e;
434 /* Copy error from polkit reply */
435 e = sd_bus_message_get_error(q->reply);
436 sd_bus_error_copy(error, e);
438 /* Treat no PK available as access denied */
439 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
442 return -sd_bus_error_get_errno(e);
445 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
447 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
456 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
462 r = sd_bus_query_sender_privilege(call, capability);
469 if (sd_bus_get_current_message(call->bus) != call)
472 callback = sd_bus_get_current_handler(call->bus);
476 userdata = sd_bus_get_current_userdata(call->bus);
478 sender = sd_bus_message_get_sender(call);
482 c = sd_bus_message_get_allow_interactive_authorization(call);
488 r = hashmap_ensure_allocated(registry, NULL);
492 r = sd_bus_message_new_method_call(
495 "org.freedesktop.PolicyKit1",
496 "/org/freedesktop/PolicyKit1/Authority",
497 "org.freedesktop.PolicyKit1.Authority",
498 "CheckAuthorization");
502 r = sd_bus_message_append(
505 "system-bus-name", 1, "name", "s", sender,
510 r = sd_bus_message_open_container(pk, 'a', "{ss}");
514 STRV_FOREACH_PAIR(k, v, details) {
515 r = sd_bus_message_append(pk, "{ss}", *k, *v);
520 r = sd_bus_message_close_container(pk);
524 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
528 q = new0(AsyncPolkitQuery, 1);
532 q->request = sd_bus_message_ref(call);
533 q->callback = callback;
534 q->userdata = userdata;
536 r = hashmap_put(*registry, call, q);
538 async_polkit_query_free(q);
542 q->registry = *registry;
544 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
546 async_polkit_query_free(q);
556 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
560 while ((q = hashmap_steal_first(registry)))
561 async_polkit_query_free(q);
563 hashmap_free(registry);
567 #if 0 /// UNNEEDED by elogind
568 int bus_check_peercred(sd_bus *c) {
575 fd = sd_bus_get_fd(c);
579 l = sizeof(struct ucred);
580 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
583 if (l != sizeof(struct ucred))
586 if (ucred.uid != 0 && ucred.uid != geteuid())
592 int bus_connect_system_systemd(sd_bus **_bus) {
593 _cleanup_bus_unref_ sd_bus *bus = NULL;
599 return sd_bus_default_system(_bus);
601 /* If we are root and kdbus is not available, then let's talk
602 * directly to the system instance, instead of going via the
605 r = sd_bus_new(&bus);
609 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
613 bus->bus_client = true;
615 r = sd_bus_start(bus);
622 bus = sd_bus_unref(bus);
624 r = sd_bus_new(&bus);
628 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
632 r = sd_bus_start(bus);
634 return sd_bus_default_system(_bus);
636 r = bus_check_peercred(bus);
646 int bus_connect_user_systemd(sd_bus **_bus) {
647 _cleanup_bus_unref_ sd_bus *bus = NULL;
648 _cleanup_free_ char *ee = NULL;
652 /* Try via kdbus first, and then directly */
656 r = sd_bus_new(&bus);
660 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
663 bus->bus_client = true;
665 r = sd_bus_start(bus);
672 bus = sd_bus_unref(bus);
674 e = secure_getenv("XDG_RUNTIME_DIR");
676 return sd_bus_default_user(_bus);
678 ee = bus_address_escape(e);
682 r = sd_bus_new(&bus);
686 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
690 r = sd_bus_start(bus);
692 return sd_bus_default_user(_bus);
694 r = bus_check_peercred(bus);
705 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
707 const char *contents;
713 r = sd_bus_message_peek_type(property, &type, &contents);
719 case SD_BUS_TYPE_STRING: {
722 r = sd_bus_message_read_basic(property, type, &s);
726 if (all || !isempty(s)) {
727 _cleanup_free_ char *escaped = NULL;
729 escaped = xescape(s, "\n");
733 printf("%s=%s\n", name, escaped);
739 case SD_BUS_TYPE_BOOLEAN: {
742 r = sd_bus_message_read_basic(property, type, &b);
746 printf("%s=%s\n", name, yes_no(b));
751 case SD_BUS_TYPE_UINT64: {
754 r = sd_bus_message_read_basic(property, type, &u);
758 /* Yes, heuristics! But we can change this check
759 * should it turn out to not be sufficient */
761 if (endswith(name, "Timestamp")) {
762 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
764 t = format_timestamp(timestamp, sizeof(timestamp), u);
766 printf("%s=%s\n", name, strempty(t));
768 } else if (strstr(name, "USec")) {
769 char timespan[FORMAT_TIMESPAN_MAX];
771 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
773 printf("%s=%llu\n", name, (unsigned long long) u);
778 case SD_BUS_TYPE_INT64: {
781 r = sd_bus_message_read_basic(property, type, &i);
785 printf("%s=%lld\n", name, (long long) i);
790 case SD_BUS_TYPE_UINT32: {
793 r = sd_bus_message_read_basic(property, type, &u);
797 if (strstr(name, "UMask") || strstr(name, "Mode"))
798 printf("%s=%04o\n", name, u);
800 printf("%s=%u\n", name, (unsigned) u);
805 case SD_BUS_TYPE_INT32: {
808 r = sd_bus_message_read_basic(property, type, &i);
812 printf("%s=%i\n", name, (int) i);
816 case SD_BUS_TYPE_DOUBLE: {
819 r = sd_bus_message_read_basic(property, type, &d);
823 printf("%s=%g\n", name, d);
827 case SD_BUS_TYPE_ARRAY:
828 if (streq(contents, "s")) {
832 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
836 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
837 _cleanup_free_ char *escaped = NULL;
842 escaped = xescape(str, "\n ");
846 printf("%s%s", first ? "" : " ", escaped);
858 r = sd_bus_message_exit_container(property);
864 } else if (streq(contents, "y")) {
868 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
877 for (i = 0; i < n; i++)
878 printf("%02x", u[i]);
885 } else if (streq(contents, "u")) {
889 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
898 for (i = 0; i < n; i++)
899 printf("%08x", u[i]);
913 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
914 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
915 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
921 r = sd_bus_call_method(bus,
924 "org.freedesktop.DBus.Properties",
932 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
936 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
938 const char *contents;
940 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
944 if (!filter || strv_find(filter, name)) {
945 r = sd_bus_message_peek_type(reply, NULL, &contents);
949 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
953 r = bus_print_property(name, reply, all);
958 printf("%s=[unprintable]\n", name);
959 /* skip what we didn't read */
960 r = sd_bus_message_skip(reply, contents);
965 r = sd_bus_message_exit_container(reply);
969 r = sd_bus_message_skip(reply, "v");
974 r = sd_bus_message_exit_container(reply);
981 r = sd_bus_message_exit_container(reply);
988 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
989 sd_id128_t *p = userdata;
994 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1001 memcpy((*p).bytes, v, n);
1008 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1012 r = sd_bus_message_peek_type(m, &type, NULL);
1017 case SD_BUS_TYPE_STRING: {
1019 char **p = userdata;
1021 r = sd_bus_message_read_basic(m, type, &s);
1028 r = free_and_strdup(p, s);
1032 case SD_BUS_TYPE_ARRAY: {
1033 _cleanup_strv_free_ char **l = NULL;
1034 char ***p = userdata;
1036 r = bus_message_read_strv_extend(m, &l);
1047 case SD_BUS_TYPE_BOOLEAN: {
1051 r = sd_bus_message_read_basic(m, type, &b);
1060 case SD_BUS_TYPE_UINT32: {
1062 uint32_t *p = userdata;
1064 r = sd_bus_message_read_basic(m, type, &u);
1073 case SD_BUS_TYPE_UINT64: {
1075 uint64_t *p = userdata;
1077 r = sd_bus_message_read_basic(m, type, &t);
1093 int bus_message_map_all_properties(
1095 const struct bus_properties_map *map,
1098 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1104 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1108 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1109 const struct bus_properties_map *prop;
1111 const char *contents;
1115 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1119 for (i = 0, prop = NULL; map[i].member; i++)
1120 if (streq(map[i].member, member)) {
1126 r = sd_bus_message_peek_type(m, NULL, &contents);
1130 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1134 v = (uint8_t *)userdata + prop->offset;
1136 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1138 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1142 r = sd_bus_message_exit_container(m);
1146 r = sd_bus_message_skip(m, "v");
1151 r = sd_bus_message_exit_container(m);
1158 return sd_bus_message_exit_container(m);
1161 #if 0 /// UNNEEDED by elogind
1162 int bus_message_map_properties_changed(
1164 const struct bus_properties_map *map,
1168 int r, invalidated, i;
1173 r = bus_message_map_all_properties(m, map, userdata);
1177 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1182 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1183 for (i = 0; map[i].member; i++)
1184 if (streq(map[i].member, member)) {
1191 r = sd_bus_message_exit_container(m);
1199 int bus_map_all_properties(
1201 const char *destination,
1203 const struct bus_properties_map *map,
1206 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1207 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1211 assert(destination);
1215 r = sd_bus_call_method(
1219 "org.freedesktop.DBus.Properties",
1227 return bus_message_map_all_properties(m, map, userdata);
1230 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1233 assert(transport >= 0);
1234 assert(transport < _BUS_TRANSPORT_MAX);
1237 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1238 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1240 switch (transport) {
1242 case BUS_TRANSPORT_LOCAL:
1243 #if 0 /// elogind does not support a user bus
1245 r = sd_bus_default_user(bus);
1248 r = sd_bus_default_system(bus);
1252 case BUS_TRANSPORT_REMOTE:
1253 r = sd_bus_open_system_remote(bus, host);
1256 case BUS_TRANSPORT_MACHINE:
1257 r = sd_bus_open_system_machine(bus, host);
1261 assert_not_reached("Hmm, unknown transport type.");
1267 #if 0 /// UNNEEDED by elogind
1268 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1271 assert(transport >= 0);
1272 assert(transport < _BUS_TRANSPORT_MAX);
1275 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1276 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1278 switch (transport) {
1280 case BUS_TRANSPORT_LOCAL:
1282 r = bus_connect_user_systemd(bus);
1284 r = bus_connect_system_systemd(bus);
1288 case BUS_TRANSPORT_REMOTE:
1289 r = sd_bus_open_system_remote(bus, host);
1292 case BUS_TRANSPORT_MACHINE:
1293 r = sd_bus_open_system_machine(bus, host);
1297 assert_not_reached("Hmm, unknown transport type.");
1304 int bus_property_get_bool(
1307 const char *interface,
1308 const char *property,
1309 sd_bus_message *reply,
1311 sd_bus_error *error) {
1313 int b = *(bool*) userdata;
1315 return sd_bus_message_append_basic(reply, 'b', &b);
1318 #if __SIZEOF_SIZE_T__ != 8
1319 int bus_property_get_size(
1322 const char *interface,
1323 const char *property,
1324 sd_bus_message *reply,
1326 sd_bus_error *error) {
1328 uint64_t sz = *(size_t*) userdata;
1330 return sd_bus_message_append_basic(reply, 't', &sz);
1334 #if __SIZEOF_LONG__ != 8
1335 int bus_property_get_long(
1338 const char *interface,
1339 const char *property,
1340 sd_bus_message *reply,
1342 sd_bus_error *error) {
1344 int64_t l = *(long*) userdata;
1346 return sd_bus_message_append_basic(reply, 'x', &l);
1349 int bus_property_get_ulong(
1352 const char *interface,
1353 const char *property,
1354 sd_bus_message *reply,
1356 sd_bus_error *error) {
1358 uint64_t ul = *(unsigned long*) userdata;
1360 return sd_bus_message_append_basic(reply, 't', &ul);
1364 int bus_log_parse_error(int r) {
1365 return log_error_errno(r, "Failed to parse bus message: %m");
1368 #if 0 /// UNNEEDED by elogind
1369 int bus_log_create_error(int r) {
1370 return log_error_errno(r, "Failed to create bus message: %m");
1373 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1379 return sd_bus_message_read(
1394 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1395 const char *eq, *field;
1401 eq = strchr(assignment, '=');
1403 log_error("Not an assignment: %s", assignment);
1407 field = strndupa(assignment, eq - assignment);
1410 if (streq(field, "CPUQuota")) {
1414 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1416 return bus_log_create_error(r);
1418 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1420 } else if (endswith(eq, "%")) {
1423 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1424 log_error("CPU quota '%s' invalid.", eq);
1428 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1430 return bus_log_create_error(r);
1432 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1434 log_error("CPU quota needs to be in percent.");
1439 return bus_log_create_error(r);
1443 } else if (streq(field, "EnvironmentFile")) {
1445 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles");
1447 return bus_log_create_error(r);
1449 r = sd_bus_message_append(m, "v", "a(sb)", 1,
1450 eq[0] == '-' ? eq + 1 : eq,
1453 return bus_log_create_error(r);
1457 } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec")) {
1461 r = parse_sec(eq, &t);
1463 return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
1466 n = newa(char, l + 2);
1470 /* Change suffix Sec → USec */
1471 strcpy(mempcpy(n, field, l - 3), "USec");
1472 r = sd_bus_message_append(m, "sv", n, "t", t);
1474 return bus_log_create_error(r);
1479 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1481 return bus_log_create_error(r);
1483 if (STR_IN_SET(field,
1484 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1485 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1486 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1487 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
1488 "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
1490 r = parse_boolean(eq);
1492 return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
1494 r = sd_bus_message_append(m, "v", "b", r);
1496 } else if (streq(field, "MemoryLimit")) {
1499 if (isempty(eq) || streq(eq, "infinity"))
1500 bytes = (uint64_t) -1;
1502 r = parse_size(eq, 1024, &bytes);
1504 log_error("Failed to parse bytes specification %s", assignment);
1509 r = sd_bus_message_append(m, "v", "t", bytes);
1511 } else if (streq(field, "TasksMax")) {
1514 if (isempty(eq) || streq(eq, "infinity"))
1517 r = safe_atou64(eq, &n);
1519 log_error("Failed to parse maximum tasks specification %s", assignment);
1524 r = sd_bus_message_append(m, "v", "t", n);
1526 } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
1529 r = cg_cpu_shares_parse(eq, &u);
1531 log_error("Failed to parse %s value %s.", field, eq);
1535 r = sd_bus_message_append(m, "v", "t", u);
1537 } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
1540 r = cg_cpu_shares_parse(eq, &u);
1542 log_error("Failed to parse %s value %s.", field, eq);
1546 r = sd_bus_message_append(m, "v", "t", u);
1548 } else if (STR_IN_SET(field,
1549 "User", "Group", "DevicePolicy", "KillMode",
1550 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1551 "StandardInput", "StandardOutput", "StandardError",
1552 "Description", "Slice", "Type", "WorkingDirectory",
1553 "RootDirectory", "SyslogIdentifier", "ProtectSystem",
1555 r = sd_bus_message_append(m, "v", "s", eq);
1557 else if (streq(field, "SyslogLevel")) {
1560 level = log_level_from_string(eq);
1562 log_error("Failed to parse %s value %s.", field, eq);
1566 r = sd_bus_message_append(m, "v", "i", level);
1568 } else if (streq(field, "SyslogFacility")) {
1571 facility = log_facility_unshifted_from_string(eq);
1573 log_error("Failed to parse %s value %s.", field, eq);
1577 r = sd_bus_message_append(m, "v", "i", facility);
1579 } else if (streq(field, "DeviceAllow")) {
1582 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1584 const char *path, *rwm, *e;
1586 e = strchr(eq, ' ');
1588 path = strndupa(eq, e - eq);
1595 if (!path_startswith(path, "/dev")) {
1596 log_error("%s is not a device file in /dev.", path);
1600 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1603 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1606 r = sd_bus_message_append(m, "v", "a(st)", 0);
1608 const char *path, *bandwidth, *e;
1611 e = strchr(eq, ' ');
1613 path = strndupa(eq, e - eq);
1616 log_error("Failed to parse %s value %s.", field, eq);
1620 if (!path_startswith(path, "/dev")) {
1621 log_error("%s is not a device file in /dev.", path);
1625 r = parse_size(bandwidth, 1000, &bytes);
1627 log_error("Failed to parse byte value %s.", bandwidth);
1631 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1634 } else if (streq(field, "BlockIODeviceWeight")) {
1637 r = sd_bus_message_append(m, "v", "a(st)", 0);
1639 const char *path, *weight, *e;
1642 e = strchr(eq, ' ');
1644 path = strndupa(eq, e - eq);
1647 log_error("Failed to parse %s value %s.", field, eq);
1651 if (!path_startswith(path, "/dev")) {
1652 log_error("%s is not a device file in /dev.", path);
1656 r = safe_atou64(weight, &u);
1658 log_error("Failed to parse %s value %s.", field, weight);
1661 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1664 } else if (rlimit_from_string(field) >= 0) {
1667 if (streq(eq, "infinity"))
1670 r = safe_atou64(eq, &rl);
1672 log_error("Invalid resource limit: %s", eq);
1677 r = sd_bus_message_append(m, "v", "t", rl);
1679 } else if (streq(field, "Nice")) {
1682 r = safe_atoi32(eq, &i);
1684 log_error("Failed to parse %s value %s.", field, eq);
1688 r = sd_bus_message_append(m, "v", "i", i);
1690 } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
1693 r = sd_bus_message_open_container(m, 'v', "as");
1695 return bus_log_create_error(r);
1697 r = sd_bus_message_open_container(m, 'a', "s");
1699 return bus_log_create_error(r);
1704 _cleanup_free_ char *word = NULL;
1706 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
1708 log_error("Failed to parse Environment value %s", eq);
1714 if (streq(field, "Environment")) {
1715 if (!env_assignment_is_valid(word)) {
1716 log_error("Invalid environment assignment: %s", word);
1719 } else { /* PassEnvironment */
1720 if (!env_name_is_valid(word)) {
1721 log_error("Invalid environment variable name: %s", word);
1726 r = sd_bus_message_append_basic(m, 's', word);
1728 return bus_log_create_error(r);
1731 r = sd_bus_message_close_container(m);
1733 return bus_log_create_error(r);
1735 r = sd_bus_message_close_container(m);
1737 } else if (streq(field, "KillSignal")) {
1740 sig = signal_from_string_try_harder(eq);
1742 log_error("Failed to parse %s value %s.", field, eq);
1746 r = sd_bus_message_append(m, "v", "i", sig);
1748 } else if (streq(field, "TimerSlackNSec")) {
1751 r = parse_nsec(eq, &n);
1753 log_error("Failed to parse %s value %s", field, eq);
1757 r = sd_bus_message_append(m, "v", "t", n);
1758 } else if (streq(field, "OOMScoreAdjust")) {
1761 r = safe_atoi(eq, &oa);
1763 log_error("Failed to parse %s value %s", field, eq);
1767 if (!oom_score_adjust_is_valid(oa)) {
1768 log_error("OOM score adjust value out of range");
1772 r = sd_bus_message_append(m, "v", "i", oa);
1773 } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1776 r = sd_bus_message_open_container(m, 'v', "as");
1778 return bus_log_create_error(r);
1780 r = sd_bus_message_open_container(m, 'a', "s");
1782 return bus_log_create_error(r);
1787 _cleanup_free_ char *word = NULL;
1790 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1792 log_error("Failed to parse %s value %s", field, eq);
1798 if (!utf8_is_valid(word)) {
1799 log_error("Failed to parse %s value %s", field, eq);
1803 offset = word[0] == '-';
1804 if (!path_is_absolute(word + offset)) {
1805 log_error("Failed to parse %s value %s", field, eq);
1809 path_kill_slashes(word + offset);
1811 r = sd_bus_message_append_basic(m, 's', word);
1813 return bus_log_create_error(r);
1816 r = sd_bus_message_close_container(m);
1818 return bus_log_create_error(r);
1820 r = sd_bus_message_close_container(m);
1822 } else if (streq(field, "RuntimeDirectory")) {
1825 r = sd_bus_message_open_container(m, 'v', "as");
1827 return bus_log_create_error(r);
1829 r = sd_bus_message_open_container(m, 'a', "s");
1831 return bus_log_create_error(r);
1836 _cleanup_free_ char *word = NULL;
1838 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1840 return log_error_errno(r, "Failed to parse %s value %s", field, eq);
1845 r = sd_bus_message_append_basic(m, 's', word);
1847 return bus_log_create_error(r);
1850 r = sd_bus_message_close_container(m);
1852 return bus_log_create_error(r);
1854 r = sd_bus_message_close_container(m);
1857 log_error("Unknown assignment %s.", assignment);
1862 return bus_log_create_error(r);
1868 typedef struct BusWaitForJobs {
1875 sd_bus_slot *slot_job_removed;
1876 sd_bus_slot *slot_disconnected;
1879 #if 0 /// UNNEEDED by elogind
1880 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1883 log_error("Warning! D-Bus connection terminated.");
1884 sd_bus_close(sd_bus_message_get_bus(m));
1889 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1890 const char *path, *unit, *result;
1891 BusWaitForJobs *d = userdata;
1899 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1901 bus_log_parse_error(r);
1905 found = set_remove(d->jobs, (char*) path);
1911 if (!isempty(result))
1912 d->result = strdup(result);
1915 d->name = strdup(unit);
1920 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1924 set_free_free(d->jobs);
1926 sd_bus_slot_unref(d->slot_disconnected);
1927 sd_bus_slot_unref(d->slot_job_removed);
1929 sd_bus_unref(d->bus);
1937 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1938 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1944 d = new0(BusWaitForJobs, 1);
1948 d->bus = sd_bus_ref(bus);
1950 /* When we are a bus client we match by sender. Direct
1951 * connections OTOH have no initialized sender field, and
1952 * hence we ignore the sender then */
1953 r = sd_bus_add_match(
1955 &d->slot_job_removed,
1958 "sender='org.freedesktop.systemd1',"
1959 "interface='org.freedesktop.systemd1.Manager',"
1960 "member='JobRemoved',"
1961 "path='/org/freedesktop/systemd1'" :
1963 "interface='org.freedesktop.systemd1.Manager',"
1964 "member='JobRemoved',"
1965 "path='/org/freedesktop/systemd1'",
1966 match_job_removed, d);
1970 r = sd_bus_add_match(
1972 &d->slot_disconnected,
1974 "sender='org.freedesktop.DBus.Local',"
1975 "interface='org.freedesktop.DBus.Local',"
1976 "member='Disconnected'",
1977 match_disconnected, d);
1987 static int bus_process_wait(sd_bus *bus) {
1991 r = sd_bus_process(bus, NULL);
1997 r = sd_bus_wait(bus, (uint64_t) -1);
2003 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
2004 _cleanup_free_ char *dbus_path = NULL;
2010 dbus_path = unit_dbus_path_from_name(d->name);
2014 return sd_bus_get_property_string(d->bus,
2015 "org.freedesktop.systemd1",
2017 "org.freedesktop.systemd1.Service",
2023 static const struct {
2024 const char *result, *explanation;
2025 } explanations [] = {
2026 { "resources", "a configured resource limit was exceeded" },
2027 { "timeout", "a timeout was exceeded" },
2028 { "exit-code", "the control process exited with error code" },
2029 { "signal", "a fatal signal was delivered to the control process" },
2030 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
2031 { "watchdog", "the service failed to send watchdog ping" },
2032 { "start-limit", "start of the service was attempted too often" }
2035 static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) {
2036 _cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL;
2040 service_shell_quoted = shell_maybe_quote(service);
2042 systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL);
2043 if (!systemctl_extra_args) {
2048 systemctl_extra_args = strstrip(systemctl_extra_args);
2050 if (!isempty(result)) {
2053 for (i = 0; i < ELEMENTSOF(explanations); ++i)
2054 if (streq(result, explanations[i].result))
2057 if (i < ELEMENTSOF(explanations)) {
2058 log_error("Job for %s failed because %s. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
2060 explanations[i].explanation,
2061 systemctl_extra_args,
2062 strna(service_shell_quoted));
2068 log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
2070 systemctl_extra_args,
2071 strna(service_shell_quoted));
2074 /* For some results maybe additional explanation is required */
2075 if (streq_ptr(result, "start-limit"))
2076 log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.",
2077 systemctl_extra_args,
2078 strna(service_shell_quoted));
2081 static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) {
2087 if (streq(d->result, "canceled"))
2088 log_error("Job for %s canceled.", strna(d->name));
2089 else if (streq(d->result, "timeout"))
2090 log_error("Job for %s timed out.", strna(d->name));
2091 else if (streq(d->result, "dependency"))
2092 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2093 else if (streq(d->result, "invalid"))
2094 log_error("%s is not active, cannot reload.", strna(d->name));
2095 else if (streq(d->result, "assert"))
2096 log_error("Assertion failed on job for %s.", strna(d->name));
2097 else if (streq(d->result, "unsupported"))
2098 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2099 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2102 _cleanup_free_ char *result = NULL;
2104 q = bus_job_get_service_result(d, &result);
2106 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
2108 log_job_error_with_service_result(d->name, result, extra_args);
2110 log_error("Job failed. See \"journalctl -xe\" for details.");
2114 if (streq(d->result, "canceled"))
2116 else if (streq(d->result, "timeout"))
2118 else if (streq(d->result, "dependency"))
2120 else if (streq(d->result, "invalid"))
2122 else if (streq(d->result, "assert"))
2124 else if (streq(d->result, "unsupported"))
2126 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2132 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) {
2137 while (!set_isempty(d->jobs)) {
2140 q = bus_process_wait(d->bus);
2142 return log_error_errno(q, "Failed to wait for response: %m");
2145 q = check_wait_response(d, quiet, extra_args);
2146 /* Return the first error as it is most likely to be
2148 if (q < 0 && r == 0)
2151 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
2154 d->name = mfree(d->name);
2155 d->result = mfree(d->result);
2161 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
2166 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
2170 return set_put_strdup(d->jobs, path);
2173 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
2176 r = bus_wait_for_jobs_add(d, path);
2180 return bus_wait_for_jobs(d, quiet, NULL);
2183 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
2184 const char *type, *path, *source;
2187 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
2189 return bus_log_parse_error(r);
2191 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
2193 if (streq(type, "symlink"))
2194 log_info("Created symlink from %s to %s.", path, source);
2196 log_info("Removed symlink %s.", path);
2199 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
2204 return bus_log_parse_error(r);
2206 r = sd_bus_message_exit_container(m);
2208 return bus_log_parse_error(r);
2214 * bus_path_encode_unique() - encode unique object path
2215 * @b: bus connection or NULL
2216 * @prefix: object path prefix
2217 * @sender_id: unique-name of client, or NULL
2218 * @external_id: external ID to be chosen by client, or NULL
2219 * @ret_path: storage for encoded object path pointer
2221 * Whenever we provide a bus API that allows clients to create and manage
2222 * server-side objects, we need to provide a unique name for these objects. If
2223 * we let the server choose the name, we suffer from a race condition: If a
2224 * client creates an object asynchronously, it cannot destroy that object until
2225 * it received the method reply. It cannot know the name of the new object,
2226 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2228 * Therefore, many APIs allow the client to choose the unique name for newly
2229 * created objects. There're two problems to solve, though:
2230 * 1) Object names are usually defined via dbus object paths, which are
2231 * usually globally namespaced. Therefore, multiple clients must be able
2232 * to choose unique object names without interference.
2233 * 2) If multiple libraries share the same bus connection, they must be
2234 * able to choose unique object names without interference.
2235 * The first problem is solved easily by prefixing a name with the
2236 * unique-bus-name of a connection. The server side must enforce this and
2237 * reject any other name. The second problem is solved by providing unique
2238 * suffixes from within sd-bus.
2240 * This helper allows clients to create unique object-paths. It uses the
2241 * template '/prefix/sender_id/external_id' and returns the new path in
2242 * @ret_path (must be freed by the caller).
2243 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2244 * NULL, this function allocates a unique suffix via @b (by requesting a new
2245 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2248 * Returns: 0 on success, negative error code on failure.
2250 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2251 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2252 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2255 assert_return(b || (sender_id && external_id), -EINVAL);
2256 assert_return(object_path_is_valid(prefix), -EINVAL);
2257 assert_return(ret_path, -EINVAL);
2260 r = sd_bus_get_unique_name(b, &sender_id);
2266 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2267 external_id = external_buf;
2270 sender_label = bus_label_escape(sender_id);
2274 external_label = bus_label_escape(external_id);
2275 if (!external_label)
2278 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2287 * bus_path_decode_unique() - decode unique object path
2288 * @path: object path to decode
2289 * @prefix: object path prefix
2290 * @ret_sender: output parameter for sender-id label
2291 * @ret_external: output parameter for external-id label
2293 * This does the reverse of bus_path_encode_unique() (see its description for
2294 * details). Both trailing labels, sender-id and external-id, are unescaped and
2295 * returned in the given output parameters (the caller must free them).
2297 * Note that this function returns 0 if the path does not match the template
2298 * (see bus_path_encode_unique()), 1 if it matched.
2300 * Returns: Negative error code on failure, 0 if the given object path does not
2301 * match the template (return parameters are set to NULL), 1 if it was
2302 * parsed successfully (return parameters contain allocated labels).
2304 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2306 char *sender, *external;
2308 assert(object_path_is_valid(path));
2309 assert(object_path_is_valid(prefix));
2311 assert(ret_external);
2313 p = object_path_startswith(path, prefix);
2316 *ret_external = NULL;
2323 *ret_external = NULL;
2327 sender = bus_label_unescape_n(p, q - p);
2328 external = bus_label_unescape(q + 1);
2329 if (!sender || !external) {
2335 *ret_sender = sender;
2336 *ret_external = external;
2341 bool is_kdbus_wanted(void) {
2342 _cleanup_free_ char *value = NULL;
2344 const bool configured = true;
2346 const bool configured = false;
2351 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2354 r = get_proc_cmdline_key("kdbus=", &value);
2358 return parse_boolean(value) == 1;
2361 bool is_kdbus_available(void) {
2362 _cleanup_close_ int fd = -1;
2363 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2365 if (!is_kdbus_wanted())
2368 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2372 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2375 #if 0 /// UNNEEDED by elogind
2376 int bus_property_get_rlimit(
2379 const char *interface,
2380 const char *property,
2381 sd_bus_message *reply,
2383 sd_bus_error *error) {
2388 const char *is_soft;
2394 is_soft = endswith(property, "Soft");
2395 rl = *(struct rlimit**) userdata;
2397 x = is_soft ? rl->rlim_cur : rl->rlim_max;
2399 struct rlimit buf = {};
2403 s = is_soft ? strndupa(property, is_soft - property) : property;
2405 z = rlimit_from_string(strstr(s, "Limit"));
2409 x = is_soft ? buf.rlim_cur : buf.rlim_max;
2412 /* rlim_t might have different sizes, let's map
2413 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2415 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
2417 return sd_bus_message_append(reply, "t", u);