2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/ioctl.h>
27 #include <sys/resource.h>
28 #include <sys/socket.h>
31 #include "sd-bus-protocol.h"
33 #include "sd-daemon.h"
37 #include "alloc-util.h"
38 #include "bus-internal.h"
39 #include "bus-label.h"
40 #include "bus-message.h"
42 #include "cgroup-util.h"
44 //#include "env-util.h"
46 #include "extract-word.h"
49 //#include "install.h"
54 #include "parse-util.h"
55 #include "path-util.h"
56 #include "proc-cmdline.h"
57 #include "process-util.h"
58 //#include "rlimit-util.h"
60 #include "signal-util.h"
61 #include "stdio-util.h"
62 #include "string-util.h"
64 #include "syslog-util.h"
65 #include "time-util.h"
66 #include "unit-name.h"
67 #include "user-util.h"
71 #if 0 /// UNNEEDED by elogind
72 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
73 sd_event *e = userdata;
78 sd_bus_close(sd_bus_message_get_bus(m));
84 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
85 _cleanup_free_ char *match = NULL;
93 /* We unregister the name here and then wait for the
94 * NameOwnerChanged signal for this event to arrive before we
95 * quit. We do this in order to make sure that any queued
96 * requests are still processed before we really exit. */
98 r = sd_bus_get_unique_name(bus, &unique);
103 "sender='org.freedesktop.DBus',"
105 "interface='org.freedesktop.DBus',"
106 "member='NameOwnerChanged',"
107 "path='/org/freedesktop/DBus',"
110 "arg2=''", name, unique);
114 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
118 r = sd_bus_release_name(bus, name);
125 int bus_event_loop_with_idle(
130 check_idle_t check_idle,
132 bool exiting = false;
142 r = sd_event_get_state(e);
145 if (r == SD_EVENT_FINISHED)
149 idle = check_idle(userdata);
153 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
157 if (r == 0 && !exiting && idle) {
159 r = sd_bus_try_close(bus);
163 /* Fallback for dbus1 connections: we
164 * unregister the name and wait for the
165 * response to come through for it */
166 if (r == -EOPNOTSUPP) {
168 /* Inform the service manager that we
169 * are going down, so that it will
170 * queue all further start requests,
171 * instead of assuming we are already
173 sd_notify(false, "STOPPING=1");
175 r = bus_async_unregister_and_exit(e, bus, name);
191 r = sd_event_get_exit_code(e, &code);
199 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
200 _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
201 int r, has_owner = 0;
206 r = sd_bus_call_method(c,
207 "org.freedesktop.DBus",
208 "/org/freedesktop/dbus",
209 "org.freedesktop.DBus",
218 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
220 return sd_bus_error_set_errno(error, r);
225 static int check_good_user(sd_bus_message *m, uid_t good_user) {
226 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
232 if (good_user == UID_INVALID)
235 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
239 /* Don't trust augmented credentials for authorization */
240 assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
242 r = sd_bus_creds_get_euid(creds, &sender_uid);
246 return sender_uid == good_user;
250 sd_bus_message *call,
253 const char **details,
263 /* Tests non-interactively! */
265 r = check_good_user(call, good_user);
269 r = sd_bus_query_sender_privilege(call, capability);
276 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
277 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
278 int authorized = false, challenge = false;
279 const char *sender, **k, **v;
281 sender = sd_bus_message_get_sender(call);
285 r = sd_bus_message_new_method_call(
288 "org.freedesktop.PolicyKit1",
289 "/org/freedesktop/PolicyKit1/Authority",
290 "org.freedesktop.PolicyKit1.Authority",
291 "CheckAuthorization");
295 r = sd_bus_message_append(
298 "system-bus-name", 1, "name", "s", sender,
303 r = sd_bus_message_open_container(request, 'a', "{ss}");
307 STRV_FOREACH_PAIR(k, v, details) {
308 r = sd_bus_message_append(request, "{ss}", *k, *v);
313 r = sd_bus_message_close_container(request);
317 r = sd_bus_message_append(request, "us", 0, NULL);
321 r = sd_bus_call(call->bus, request, 0, e, &reply);
323 /* Treat no PK available as access denied */
324 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
325 sd_bus_error_free(e);
332 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
336 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
344 *_challenge = challenge;
355 typedef struct AsyncPolkitQuery {
356 sd_bus_message *request, *reply;
357 sd_bus_message_handler_t callback;
363 static void async_polkit_query_free(AsyncPolkitQuery *q) {
368 sd_bus_slot_unref(q->slot);
370 if (q->registry && q->request)
371 hashmap_remove(q->registry, q->request);
373 sd_bus_message_unref(q->request);
374 sd_bus_message_unref(q->reply);
379 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
380 _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
381 AsyncPolkitQuery *q = userdata;
387 q->slot = sd_bus_slot_unref(q->slot);
388 q->reply = sd_bus_message_ref(reply);
390 r = sd_bus_message_rewind(q->request, true);
392 r = sd_bus_reply_method_errno(q->request, r, NULL);
396 r = q->callback(q->request, q->userdata, &error_buffer);
397 r = bus_maybe_reply_error(q->request, r, &error_buffer);
400 async_polkit_query_free(q);
407 int bus_verify_polkit_async(
408 sd_bus_message *call,
411 const char **details,
415 sd_bus_error *error) {
418 _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
420 const char *sender, **k, **v;
421 sd_bus_message_handler_t callback;
431 r = check_good_user(call, good_user);
436 q = hashmap_get(*registry, call);
438 int authorized, challenge;
440 /* This is the second invocation of this function, and
441 * there's already a response from polkit, let's
445 if (sd_bus_message_is_method_error(q->reply, NULL)) {
446 const sd_bus_error *e;
448 /* Copy error from polkit reply */
449 e = sd_bus_message_get_error(q->reply);
450 sd_bus_error_copy(error, e);
452 /* Treat no PK available as access denied */
453 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
456 return -sd_bus_error_get_errno(e);
459 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
461 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
470 return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
476 r = sd_bus_query_sender_privilege(call, capability);
483 if (sd_bus_get_current_message(call->bus) != call)
486 callback = sd_bus_get_current_handler(call->bus);
490 userdata = sd_bus_get_current_userdata(call->bus);
492 sender = sd_bus_message_get_sender(call);
496 c = sd_bus_message_get_allow_interactive_authorization(call);
502 r = hashmap_ensure_allocated(registry, NULL);
506 r = sd_bus_message_new_method_call(
509 "org.freedesktop.PolicyKit1",
510 "/org/freedesktop/PolicyKit1/Authority",
511 "org.freedesktop.PolicyKit1.Authority",
512 "CheckAuthorization");
516 r = sd_bus_message_append(
519 "system-bus-name", 1, "name", "s", sender,
524 r = sd_bus_message_open_container(pk, 'a', "{ss}");
528 STRV_FOREACH_PAIR(k, v, details) {
529 r = sd_bus_message_append(pk, "{ss}", *k, *v);
534 r = sd_bus_message_close_container(pk);
538 r = sd_bus_message_append(pk, "us", !!interactive, NULL);
542 q = new0(AsyncPolkitQuery, 1);
546 q->request = sd_bus_message_ref(call);
547 q->callback = callback;
548 q->userdata = userdata;
550 r = hashmap_put(*registry, call, q);
552 async_polkit_query_free(q);
556 q->registry = *registry;
558 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
560 async_polkit_query_free(q);
570 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
574 while ((q = hashmap_steal_first(registry)))
575 async_polkit_query_free(q);
577 hashmap_free(registry);
581 #if 0 /// UNNEEDED by elogind
582 int bus_check_peercred(sd_bus *c) {
589 fd = sd_bus_get_fd(c);
593 l = sizeof(struct ucred);
594 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
597 if (l != sizeof(struct ucred))
600 if (ucred.uid != 0 && ucred.uid != geteuid())
606 int bus_connect_system_systemd(sd_bus **_bus) {
607 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
613 return sd_bus_default_system(_bus);
615 /* If we are root and kdbus is not available, then let's talk
616 * directly to the system instance, instead of going via the
619 r = sd_bus_new(&bus);
623 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
627 bus->bus_client = true;
629 r = sd_bus_start(bus);
636 bus = sd_bus_unref(bus);
638 r = sd_bus_new(&bus);
642 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
646 r = sd_bus_start(bus);
648 return sd_bus_default_system(_bus);
650 r = bus_check_peercred(bus);
660 int bus_connect_user_systemd(sd_bus **_bus) {
661 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
662 _cleanup_free_ char *ee = NULL;
666 /* Try via kdbus first, and then directly */
670 r = sd_bus_new(&bus);
674 if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
677 bus->bus_client = true;
679 r = sd_bus_start(bus);
686 bus = sd_bus_unref(bus);
688 e = secure_getenv("XDG_RUNTIME_DIR");
690 return sd_bus_default_user(_bus);
692 ee = bus_address_escape(e);
696 r = sd_bus_new(&bus);
700 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
704 r = sd_bus_start(bus);
706 return sd_bus_default_user(_bus);
708 r = bus_check_peercred(bus);
719 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
721 const char *contents;
727 r = sd_bus_message_peek_type(property, &type, &contents);
733 case SD_BUS_TYPE_STRING: {
736 r = sd_bus_message_read_basic(property, type, &s);
740 if (all || !isempty(s)) {
741 _cleanup_free_ char *escaped = NULL;
743 escaped = xescape(s, "\n");
747 printf("%s=%s\n", name, escaped);
753 case SD_BUS_TYPE_BOOLEAN: {
756 r = sd_bus_message_read_basic(property, type, &b);
760 printf("%s=%s\n", name, yes_no(b));
765 case SD_BUS_TYPE_UINT64: {
768 r = sd_bus_message_read_basic(property, type, &u);
772 /* Yes, heuristics! But we can change this check
773 * should it turn out to not be sufficient */
775 if (endswith(name, "Timestamp")) {
776 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
778 t = format_timestamp(timestamp, sizeof(timestamp), u);
780 printf("%s=%s\n", name, strempty(t));
782 } else if (strstr(name, "USec")) {
783 char timespan[FORMAT_TIMESPAN_MAX];
785 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
787 printf("%s=%llu\n", name, (unsigned long long) u);
792 case SD_BUS_TYPE_INT64: {
795 r = sd_bus_message_read_basic(property, type, &i);
799 printf("%s=%lld\n", name, (long long) i);
804 case SD_BUS_TYPE_UINT32: {
807 r = sd_bus_message_read_basic(property, type, &u);
811 if (strstr(name, "UMask") || strstr(name, "Mode"))
812 printf("%s=%04o\n", name, u);
814 printf("%s=%u\n", name, (unsigned) u);
819 case SD_BUS_TYPE_INT32: {
822 r = sd_bus_message_read_basic(property, type, &i);
826 printf("%s=%i\n", name, (int) i);
830 case SD_BUS_TYPE_DOUBLE: {
833 r = sd_bus_message_read_basic(property, type, &d);
837 printf("%s=%g\n", name, d);
841 case SD_BUS_TYPE_ARRAY:
842 if (streq(contents, "s")) {
846 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
850 while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
851 _cleanup_free_ char *escaped = NULL;
856 escaped = xescape(str, "\n ");
860 printf("%s%s", first ? "" : " ", escaped);
872 r = sd_bus_message_exit_container(property);
878 } else if (streq(contents, "y")) {
882 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
891 for (i = 0; i < n; i++)
892 printf("%02x", u[i]);
899 } else if (streq(contents, "u")) {
903 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
912 for (i = 0; i < n; i++)
913 printf("%08x", u[i]);
927 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
928 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
929 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
935 r = sd_bus_call_method(bus,
938 "org.freedesktop.DBus.Properties",
946 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
950 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
952 const char *contents;
954 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
958 if (!filter || strv_find(filter, name)) {
959 r = sd_bus_message_peek_type(reply, NULL, &contents);
963 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
967 r = bus_print_property(name, reply, all);
972 printf("%s=[unprintable]\n", name);
973 /* skip what we didn't read */
974 r = sd_bus_message_skip(reply, contents);
979 r = sd_bus_message_exit_container(reply);
983 r = sd_bus_message_skip(reply, "v");
988 r = sd_bus_message_exit_container(reply);
995 r = sd_bus_message_exit_container(reply);
1002 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1003 sd_id128_t *p = userdata;
1008 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1015 memcpy((*p).bytes, v, n);
1022 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1026 r = sd_bus_message_peek_type(m, &type, NULL);
1031 case SD_BUS_TYPE_STRING: {
1033 char **p = userdata;
1035 r = sd_bus_message_read_basic(m, type, &s);
1042 r = free_and_strdup(p, s);
1046 case SD_BUS_TYPE_ARRAY: {
1047 _cleanup_strv_free_ char **l = NULL;
1048 char ***p = userdata;
1050 r = bus_message_read_strv_extend(m, &l);
1061 case SD_BUS_TYPE_BOOLEAN: {
1065 r = sd_bus_message_read_basic(m, type, &b);
1074 case SD_BUS_TYPE_UINT32: {
1076 uint32_t *p = userdata;
1078 r = sd_bus_message_read_basic(m, type, &u);
1087 case SD_BUS_TYPE_UINT64: {
1089 uint64_t *p = userdata;
1091 r = sd_bus_message_read_basic(m, type, &t);
1107 int bus_message_map_all_properties(
1109 const struct bus_properties_map *map,
1112 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1118 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1122 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1123 const struct bus_properties_map *prop;
1125 const char *contents;
1129 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1133 for (i = 0, prop = NULL; map[i].member; i++)
1134 if (streq(map[i].member, member)) {
1140 r = sd_bus_message_peek_type(m, NULL, &contents);
1144 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1148 v = (uint8_t *)userdata + prop->offset;
1150 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1152 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1156 r = sd_bus_message_exit_container(m);
1160 r = sd_bus_message_skip(m, "v");
1165 r = sd_bus_message_exit_container(m);
1172 return sd_bus_message_exit_container(m);
1175 #if 0 /// UNNEEDED by elogind
1176 int bus_message_map_properties_changed(
1178 const struct bus_properties_map *map,
1182 int r, invalidated, i;
1187 r = bus_message_map_all_properties(m, map, userdata);
1191 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1196 while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1197 for (i = 0; map[i].member; i++)
1198 if (streq(map[i].member, member)) {
1205 r = sd_bus_message_exit_container(m);
1213 int bus_map_all_properties(
1215 const char *destination,
1217 const struct bus_properties_map *map,
1220 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1221 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1225 assert(destination);
1229 r = sd_bus_call_method(
1233 "org.freedesktop.DBus.Properties",
1241 return bus_message_map_all_properties(m, map, userdata);
1244 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1247 assert(transport >= 0);
1248 assert(transport < _BUS_TRANSPORT_MAX);
1251 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1252 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1254 switch (transport) {
1256 case BUS_TRANSPORT_LOCAL:
1257 #if 0 /// elogind does not support a user bus
1259 r = sd_bus_default_user(bus);
1262 r = sd_bus_default_system(bus);
1266 case BUS_TRANSPORT_REMOTE:
1267 r = sd_bus_open_system_remote(bus, host);
1270 case BUS_TRANSPORT_MACHINE:
1271 r = sd_bus_open_system_machine(bus, host);
1275 assert_not_reached("Hmm, unknown transport type.");
1281 #if 0 /// UNNEEDED by elogind
1282 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1285 assert(transport >= 0);
1286 assert(transport < _BUS_TRANSPORT_MAX);
1289 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1290 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1292 switch (transport) {
1294 case BUS_TRANSPORT_LOCAL:
1296 r = bus_connect_user_systemd(bus);
1298 r = bus_connect_system_systemd(bus);
1302 case BUS_TRANSPORT_REMOTE:
1303 r = sd_bus_open_system_remote(bus, host);
1306 case BUS_TRANSPORT_MACHINE:
1307 r = sd_bus_open_system_machine(bus, host);
1311 assert_not_reached("Hmm, unknown transport type.");
1318 int bus_property_get_bool(
1321 const char *interface,
1322 const char *property,
1323 sd_bus_message *reply,
1325 sd_bus_error *error) {
1327 int b = *(bool*) userdata;
1329 return sd_bus_message_append_basic(reply, 'b', &b);
1332 #if __SIZEOF_SIZE_T__ != 8
1333 int bus_property_get_size(
1336 const char *interface,
1337 const char *property,
1338 sd_bus_message *reply,
1340 sd_bus_error *error) {
1342 uint64_t sz = *(size_t*) userdata;
1344 return sd_bus_message_append_basic(reply, 't', &sz);
1348 #if __SIZEOF_LONG__ != 8
1349 int bus_property_get_long(
1352 const char *interface,
1353 const char *property,
1354 sd_bus_message *reply,
1356 sd_bus_error *error) {
1358 int64_t l = *(long*) userdata;
1360 return sd_bus_message_append_basic(reply, 'x', &l);
1363 int bus_property_get_ulong(
1366 const char *interface,
1367 const char *property,
1368 sd_bus_message *reply,
1370 sd_bus_error *error) {
1372 uint64_t ul = *(unsigned long*) userdata;
1374 return sd_bus_message_append_basic(reply, 't', &ul);
1378 int bus_log_parse_error(int r) {
1379 return log_error_errno(r, "Failed to parse bus message: %m");
1382 #if 0 /// UNNEEDED by elogind
1383 int bus_log_create_error(int r) {
1384 return log_error_errno(r, "Failed to create bus message: %m");
1387 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1393 return sd_bus_message_read(
1408 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1409 const char *eq, *field;
1415 eq = strchr(assignment, '=');
1417 log_error("Not an assignment: %s", assignment);
1421 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1423 return bus_log_create_error(r);
1425 field = strndupa(assignment, eq - assignment);
1428 if (streq(field, "CPUQuota")) {
1431 r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
1432 else if (endswith(eq, "%")) {
1435 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1436 log_error("CPU quota '%s' invalid.", eq);
1440 r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100);
1442 log_error("CPU quota needs to be in percent.");
1448 } else if (streq(field, "EnvironmentFile")) {
1450 r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
1451 eq[0] == '-' ? eq + 1 : eq,
1455 } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) {
1459 r = parse_sec(eq, &t);
1461 return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
1464 n = newa(char, l + 2);
1468 /* Change suffix Sec → USec */
1469 strcpy(mempcpy(n, field, l - 3), "USec");
1470 r = sd_bus_message_append(m, "sv", n, "t", t);
1474 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1476 return bus_log_create_error(r);
1478 rl = rlimit_from_string(field);
1483 r = rlimit_parse(rl, eq, &l);
1485 return log_error_errno(r, "Failed to parse resource limit: %s", eq);
1487 r = sd_bus_message_append(m, "v", "t", l.rlim_max);
1489 return bus_log_create_error(r);
1491 r = sd_bus_message_close_container(m);
1493 return bus_log_create_error(r);
1495 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
1497 return bus_log_create_error(r);
1499 sn = strjoina(field, "Soft");
1500 r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
1502 } else if (STR_IN_SET(field,
1503 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
1504 "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
1505 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
1506 "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
1507 "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
1509 r = parse_boolean(eq);
1511 return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
1513 r = sd_bus_message_append(m, "v", "b", r);
1515 } else if (streq(field, "MemoryLimit")) {
1518 if (isempty(eq) || streq(eq, "infinity"))
1519 bytes = (uint64_t) -1;
1521 r = parse_size(eq, 1024, &bytes);
1523 log_error("Failed to parse bytes specification %s", assignment);
1528 r = sd_bus_message_append(m, "v", "t", bytes);
1530 } else if (streq(field, "TasksMax")) {
1533 if (isempty(eq) || streq(eq, "infinity"))
1536 r = safe_atou64(eq, &n);
1538 log_error("Failed to parse maximum tasks specification %s", assignment);
1543 r = sd_bus_message_append(m, "v", "t", n);
1545 } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
1548 r = cg_cpu_shares_parse(eq, &u);
1550 log_error("Failed to parse %s value %s.", field, eq);
1554 r = sd_bus_message_append(m, "v", "t", u);
1556 } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
1559 r = cg_cpu_shares_parse(eq, &u);
1561 log_error("Failed to parse %s value %s.", field, eq);
1565 r = sd_bus_message_append(m, "v", "t", u);
1567 } else if (STR_IN_SET(field,
1568 "User", "Group", "DevicePolicy", "KillMode",
1569 "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1570 "StandardInput", "StandardOutput", "StandardError",
1571 "Description", "Slice", "Type", "WorkingDirectory",
1572 "RootDirectory", "SyslogIdentifier", "ProtectSystem",
1574 r = sd_bus_message_append(m, "v", "s", eq);
1576 else if (streq(field, "SyslogLevel")) {
1579 level = log_level_from_string(eq);
1581 log_error("Failed to parse %s value %s.", field, eq);
1585 r = sd_bus_message_append(m, "v", "i", level);
1587 } else if (streq(field, "SyslogFacility")) {
1590 facility = log_facility_unshifted_from_string(eq);
1592 log_error("Failed to parse %s value %s.", field, eq);
1596 r = sd_bus_message_append(m, "v", "i", facility);
1598 } else if (streq(field, "DeviceAllow")) {
1601 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1603 const char *path, *rwm, *e;
1605 e = strchr(eq, ' ');
1607 path = strndupa(eq, e - eq);
1614 if (!path_startswith(path, "/dev")) {
1615 log_error("%s is not a device file in /dev.", path);
1619 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1622 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1625 r = sd_bus_message_append(m, "v", "a(st)", 0);
1627 const char *path, *bandwidth, *e;
1630 e = strchr(eq, ' ');
1632 path = strndupa(eq, e - eq);
1635 log_error("Failed to parse %s value %s.", field, eq);
1639 if (!path_startswith(path, "/dev")) {
1640 log_error("%s is not a device file in /dev.", path);
1644 r = parse_size(bandwidth, 1000, &bytes);
1646 log_error("Failed to parse byte value %s.", bandwidth);
1650 r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
1653 } else if (streq(field, "BlockIODeviceWeight")) {
1656 r = sd_bus_message_append(m, "v", "a(st)", 0);
1658 const char *path, *weight, *e;
1661 e = strchr(eq, ' ');
1663 path = strndupa(eq, e - eq);
1666 log_error("Failed to parse %s value %s.", field, eq);
1670 if (!path_startswith(path, "/dev")) {
1671 log_error("%s is not a device file in /dev.", path);
1675 r = safe_atou64(weight, &u);
1677 log_error("Failed to parse %s value %s.", field, weight);
1680 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1683 } else if (streq(field, "Nice")) {
1686 r = safe_atoi32(eq, &i);
1688 log_error("Failed to parse %s value %s.", field, eq);
1692 r = sd_bus_message_append(m, "v", "i", i);
1694 } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
1697 r = sd_bus_message_open_container(m, 'v', "as");
1699 return bus_log_create_error(r);
1701 r = sd_bus_message_open_container(m, 'a', "s");
1703 return bus_log_create_error(r);
1708 _cleanup_free_ char *word = NULL;
1710 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
1712 log_error("Failed to parse Environment value %s", eq);
1718 if (streq(field, "Environment")) {
1719 if (!env_assignment_is_valid(word)) {
1720 log_error("Invalid environment assignment: %s", word);
1723 } else { /* PassEnvironment */
1724 if (!env_name_is_valid(word)) {
1725 log_error("Invalid environment variable name: %s", word);
1730 r = sd_bus_message_append_basic(m, 's', word);
1732 return bus_log_create_error(r);
1735 r = sd_bus_message_close_container(m);
1737 return bus_log_create_error(r);
1739 r = sd_bus_message_close_container(m);
1741 } else if (streq(field, "KillSignal")) {
1744 sig = signal_from_string_try_harder(eq);
1746 log_error("Failed to parse %s value %s.", field, eq);
1750 r = sd_bus_message_append(m, "v", "i", sig);
1752 } else if (streq(field, "TimerSlackNSec")) {
1755 r = parse_nsec(eq, &n);
1757 log_error("Failed to parse %s value %s", field, eq);
1761 r = sd_bus_message_append(m, "v", "t", n);
1762 } else if (streq(field, "OOMScoreAdjust")) {
1765 r = safe_atoi(eq, &oa);
1767 log_error("Failed to parse %s value %s", field, eq);
1771 if (!oom_score_adjust_is_valid(oa)) {
1772 log_error("OOM score adjust value out of range");
1776 r = sd_bus_message_append(m, "v", "i", oa);
1777 } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1780 r = sd_bus_message_open_container(m, 'v', "as");
1782 return bus_log_create_error(r);
1784 r = sd_bus_message_open_container(m, 'a', "s");
1786 return bus_log_create_error(r);
1791 _cleanup_free_ char *word = NULL;
1794 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1796 log_error("Failed to parse %s value %s", field, eq);
1802 if (!utf8_is_valid(word)) {
1803 log_error("Failed to parse %s value %s", field, eq);
1807 offset = word[0] == '-';
1808 if (!path_is_absolute(word + offset)) {
1809 log_error("Failed to parse %s value %s", field, eq);
1813 path_kill_slashes(word + offset);
1815 r = sd_bus_message_append_basic(m, 's', word);
1817 return bus_log_create_error(r);
1820 r = sd_bus_message_close_container(m);
1822 return bus_log_create_error(r);
1824 r = sd_bus_message_close_container(m);
1826 } else if (streq(field, "RuntimeDirectory")) {
1829 r = sd_bus_message_open_container(m, 'v', "as");
1831 return bus_log_create_error(r);
1833 r = sd_bus_message_open_container(m, 'a', "s");
1835 return bus_log_create_error(r);
1840 _cleanup_free_ char *word = NULL;
1842 r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
1844 return log_error_errno(r, "Failed to parse %s value %s", field, eq);
1849 r = sd_bus_message_append_basic(m, 's', word);
1851 return bus_log_create_error(r);
1854 r = sd_bus_message_close_container(m);
1856 return bus_log_create_error(r);
1858 r = sd_bus_message_close_container(m);
1861 log_error("Unknown assignment %s.", assignment);
1867 return bus_log_create_error(r);
1869 r = sd_bus_message_close_container(m);
1871 return bus_log_create_error(r);
1877 typedef struct BusWaitForJobs {
1884 sd_bus_slot *slot_job_removed;
1885 sd_bus_slot *slot_disconnected;
1888 #if 0 /// UNNEEDED by elogind
1889 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1892 log_error("Warning! D-Bus connection terminated.");
1893 sd_bus_close(sd_bus_message_get_bus(m));
1898 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1899 const char *path, *unit, *result;
1900 BusWaitForJobs *d = userdata;
1908 r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1910 bus_log_parse_error(r);
1914 found = set_remove(d->jobs, (char*) path);
1920 if (!isempty(result))
1921 d->result = strdup(result);
1924 d->name = strdup(unit);
1929 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1933 set_free_free(d->jobs);
1935 sd_bus_slot_unref(d->slot_disconnected);
1936 sd_bus_slot_unref(d->slot_job_removed);
1938 sd_bus_unref(d->bus);
1946 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1947 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1953 d = new0(BusWaitForJobs, 1);
1957 d->bus = sd_bus_ref(bus);
1959 /* When we are a bus client we match by sender. Direct
1960 * connections OTOH have no initialized sender field, and
1961 * hence we ignore the sender then */
1962 r = sd_bus_add_match(
1964 &d->slot_job_removed,
1967 "sender='org.freedesktop.systemd1',"
1968 "interface='org.freedesktop.systemd1.Manager',"
1969 "member='JobRemoved',"
1970 "path='/org/freedesktop/systemd1'" :
1972 "interface='org.freedesktop.systemd1.Manager',"
1973 "member='JobRemoved',"
1974 "path='/org/freedesktop/systemd1'",
1975 match_job_removed, d);
1979 r = sd_bus_add_match(
1981 &d->slot_disconnected,
1983 "sender='org.freedesktop.DBus.Local',"
1984 "interface='org.freedesktop.DBus.Local',"
1985 "member='Disconnected'",
1986 match_disconnected, d);
1996 static int bus_process_wait(sd_bus *bus) {
2000 r = sd_bus_process(bus, NULL);
2006 r = sd_bus_wait(bus, (uint64_t) -1);
2012 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
2013 _cleanup_free_ char *dbus_path = NULL;
2019 dbus_path = unit_dbus_path_from_name(d->name);
2023 return sd_bus_get_property_string(d->bus,
2024 "org.freedesktop.systemd1",
2026 "org.freedesktop.systemd1.Service",
2032 static const struct {
2033 const char *result, *explanation;
2034 } explanations [] = {
2035 { "resources", "a configured resource limit was exceeded" },
2036 { "timeout", "a timeout was exceeded" },
2037 { "exit-code", "the control process exited with error code" },
2038 { "signal", "a fatal signal was delivered to the control process" },
2039 { "core-dump", "a fatal signal was delivered causing the control process to dump core" },
2040 { "watchdog", "the service failed to send watchdog ping" },
2041 { "start-limit", "start of the service was attempted too often" }
2044 static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) {
2045 _cleanup_free_ char *service_shell_quoted = NULL;
2046 const char *systemctl = "systemctl", *journalctl = "journalctl";
2050 service_shell_quoted = shell_maybe_quote(service);
2052 if (extra_args && extra_args[1]) {
2053 _cleanup_free_ char *t;
2055 t = strv_join((char**) extra_args, " ");
2056 systemctl = strjoina("systemctl ", t ?: "<args>", NULL);
2057 journalctl = strjoina("journalctl ", t ?: "<args>", NULL);
2060 if (!isempty(result)) {
2063 for (i = 0; i < ELEMENTSOF(explanations); ++i)
2064 if (streq(result, explanations[i].result))
2067 if (i < ELEMENTSOF(explanations)) {
2068 log_error("Job for %s failed because %s.\n"
2069 "See \"%s status %s\" and \"%s -xe\" for details.\n",
2071 explanations[i].explanation,
2073 service_shell_quoted ?: "<service>",
2079 log_error("Job for %s failed.\n"
2080 "See \"%s status %s\" and \"%s -xe\" for details.\n",
2083 service_shell_quoted ?: "<service>",
2087 /* For some results maybe additional explanation is required */
2088 if (streq_ptr(result, "start-limit"))
2089 log_info("To force a start use \"%1$s reset-failed %2$s\"\n"
2090 "followed by \"%1$s start %2$s\" again.",
2092 service_shell_quoted ?: "<service>");
2095 static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
2101 if (streq(d->result, "canceled"))
2102 log_error("Job for %s canceled.", strna(d->name));
2103 else if (streq(d->result, "timeout"))
2104 log_error("Job for %s timed out.", strna(d->name));
2105 else if (streq(d->result, "dependency"))
2106 log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
2107 else if (streq(d->result, "invalid"))
2108 log_error("%s is not active, cannot reload.", strna(d->name));
2109 else if (streq(d->result, "assert"))
2110 log_error("Assertion failed on job for %s.", strna(d->name));
2111 else if (streq(d->result, "unsupported"))
2112 log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
2113 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
2116 _cleanup_free_ char *result = NULL;
2118 q = bus_job_get_service_result(d, &result);
2120 log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
2122 log_job_error_with_service_result(d->name, result, extra_args);
2124 log_error("Job failed. See \"journalctl -xe\" for details.");
2128 if (streq(d->result, "canceled"))
2130 else if (streq(d->result, "timeout"))
2132 else if (streq(d->result, "dependency"))
2134 else if (streq(d->result, "invalid"))
2136 else if (streq(d->result, "assert"))
2138 else if (streq(d->result, "unsupported"))
2140 else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
2146 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
2151 while (!set_isempty(d->jobs)) {
2154 q = bus_process_wait(d->bus);
2156 return log_error_errno(q, "Failed to wait for response: %m");
2159 q = check_wait_response(d, quiet, extra_args);
2160 /* Return the first error as it is most likely to be
2162 if (q < 0 && r == 0)
2165 log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
2168 d->name = mfree(d->name);
2169 d->result = mfree(d->result);
2175 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
2180 r = set_ensure_allocated(&d->jobs, &string_hash_ops);
2184 return set_put_strdup(d->jobs, path);
2187 int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
2190 r = bus_wait_for_jobs_add(d, path);
2194 return bus_wait_for_jobs(d, quiet, NULL);
2197 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
2198 const char *type, *path, *source;
2201 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
2203 return bus_log_parse_error(r);
2205 while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
2207 if (streq(type, "symlink"))
2208 log_info("Created symlink from %s to %s.", path, source);
2210 log_info("Removed symlink %s.", path);
2213 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
2218 return bus_log_parse_error(r);
2220 r = sd_bus_message_exit_container(m);
2222 return bus_log_parse_error(r);
2228 * bus_path_encode_unique() - encode unique object path
2229 * @b: bus connection or NULL
2230 * @prefix: object path prefix
2231 * @sender_id: unique-name of client, or NULL
2232 * @external_id: external ID to be chosen by client, or NULL
2233 * @ret_path: storage for encoded object path pointer
2235 * Whenever we provide a bus API that allows clients to create and manage
2236 * server-side objects, we need to provide a unique name for these objects. If
2237 * we let the server choose the name, we suffer from a race condition: If a
2238 * client creates an object asynchronously, it cannot destroy that object until
2239 * it received the method reply. It cannot know the name of the new object,
2240 * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
2242 * Therefore, many APIs allow the client to choose the unique name for newly
2243 * created objects. There're two problems to solve, though:
2244 * 1) Object names are usually defined via dbus object paths, which are
2245 * usually globally namespaced. Therefore, multiple clients must be able
2246 * to choose unique object names without interference.
2247 * 2) If multiple libraries share the same bus connection, they must be
2248 * able to choose unique object names without interference.
2249 * The first problem is solved easily by prefixing a name with the
2250 * unique-bus-name of a connection. The server side must enforce this and
2251 * reject any other name. The second problem is solved by providing unique
2252 * suffixes from within sd-bus.
2254 * This helper allows clients to create unique object-paths. It uses the
2255 * template '/prefix/sender_id/external_id' and returns the new path in
2256 * @ret_path (must be freed by the caller).
2257 * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
2258 * NULL, this function allocates a unique suffix via @b (by requesting a new
2259 * cookie). If both @sender_id and @external_id are given, @b can be passed as
2262 * Returns: 0 on success, negative error code on failure.
2264 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
2265 _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
2266 char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
2269 assert_return(b || (sender_id && external_id), -EINVAL);
2270 assert_return(object_path_is_valid(prefix), -EINVAL);
2271 assert_return(ret_path, -EINVAL);
2274 r = sd_bus_get_unique_name(b, &sender_id);
2280 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
2281 external_id = external_buf;
2284 sender_label = bus_label_escape(sender_id);
2288 external_label = bus_label_escape(external_id);
2289 if (!external_label)
2292 p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
2301 * bus_path_decode_unique() - decode unique object path
2302 * @path: object path to decode
2303 * @prefix: object path prefix
2304 * @ret_sender: output parameter for sender-id label
2305 * @ret_external: output parameter for external-id label
2307 * This does the reverse of bus_path_encode_unique() (see its description for
2308 * details). Both trailing labels, sender-id and external-id, are unescaped and
2309 * returned in the given output parameters (the caller must free them).
2311 * Note that this function returns 0 if the path does not match the template
2312 * (see bus_path_encode_unique()), 1 if it matched.
2314 * Returns: Negative error code on failure, 0 if the given object path does not
2315 * match the template (return parameters are set to NULL), 1 if it was
2316 * parsed successfully (return parameters contain allocated labels).
2318 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2320 char *sender, *external;
2322 assert(object_path_is_valid(path));
2323 assert(object_path_is_valid(prefix));
2325 assert(ret_external);
2327 p = object_path_startswith(path, prefix);
2330 *ret_external = NULL;
2337 *ret_external = NULL;
2341 sender = bus_label_unescape_n(p, q - p);
2342 external = bus_label_unescape(q + 1);
2343 if (!sender || !external) {
2349 *ret_sender = sender;
2350 *ret_external = external;
2355 bool is_kdbus_wanted(void) {
2356 _cleanup_free_ char *value = NULL;
2358 const bool configured = true;
2360 const bool configured = false;
2365 if (get_proc_cmdline_key("kdbus", NULL) > 0)
2368 r = get_proc_cmdline_key("kdbus=", &value);
2372 return parse_boolean(value) == 1;
2375 bool is_kdbus_available(void) {
2376 _cleanup_close_ int fd = -1;
2377 struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2379 if (!is_kdbus_wanted())
2382 fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2386 return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2389 #if 0 /// UNNEEDED by elogind
2390 int bus_property_get_rlimit(
2393 const char *interface,
2394 const char *property,
2395 sd_bus_message *reply,
2397 sd_bus_error *error) {
2402 const char *is_soft;
2408 is_soft = endswith(property, "Soft");
2409 rl = *(struct rlimit**) userdata;
2411 x = is_soft ? rl->rlim_cur : rl->rlim_max;
2413 struct rlimit buf = {};
2417 s = is_soft ? strndupa(property, is_soft - property) : property;
2419 z = rlimit_from_string(strstr(s, "Limit"));
2423 x = is_soft ? buf.rlim_cur : buf.rlim_max;
2426 /* rlim_t might have different sizes, let's map
2427 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
2429 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
2431 return sd_bus_message_append(reply, "t", u);