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>
23 #include <sys/capability.h>
29 #include "path-util.h"
34 #include "bus-error.h"
35 #include "bus-message.h"
37 #include "bus-internal.h"
39 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
40 sd_event *e = userdata;
52 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
53 _cleanup_free_ char *match = NULL;
61 /* We unregister the name here and then wait for the
62 * NameOwnerChanged signal for this event to arrive before we
63 * quit. We do this in order to make sure that any queued
64 * requests are still processed before we really exit. */
66 r = sd_bus_get_unique_name(bus, &unique);
71 "sender='org.freedesktop.DBus',"
73 "interface='org.freedesktop.DBus',"
74 "member='NameOwnerChanged',"
75 "path='/org/freedesktop/DBus',"
78 "arg2=''", name, unique);
82 r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
86 r = sd_bus_release_name(bus, name);
93 int bus_event_loop_with_idle(
98 check_idle_t check_idle,
100 bool exiting = false;
110 r = sd_event_get_state(e);
113 if (r == SD_EVENT_FINISHED)
117 idle = check_idle(userdata);
121 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
125 if (r == 0 && !exiting) {
127 r = sd_bus_try_close(bus);
132 /* Fallback for dbus1 connections: we
133 * unregister the name and wait for
134 * the response to come through for
137 r = bus_async_unregister_and_exit(e, bus, name);
153 r = sd_event_get_exit_code(e, &code);
160 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
161 _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
162 int r, has_owner = 0;
167 r = sd_bus_call_method(c,
168 "org.freedesktop.DBus",
169 "/org/freedesktop/dbus",
170 "org.freedesktop.DBus",
179 r = sd_bus_message_read_basic(rep, 'b', &has_owner);
181 return sd_bus_error_set_errno(error, r);
186 int bus_verify_polkit(
187 sd_bus_message *call,
199 r = sd_bus_query_sender_privilege(call, capability);
206 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
207 int authorized = false, challenge = false;
210 sender = sd_bus_message_get_sender(call);
214 r = sd_bus_call_method(
216 "org.freedesktop.PolicyKit1",
217 "/org/freedesktop/PolicyKit1/Authority",
218 "org.freedesktop.PolicyKit1.Authority",
219 "CheckAuthorization",
223 "system-bus-name", 1, "name", "s", sender,
230 /* Treat no PK available as access denied */
231 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
232 sd_bus_error_free(e);
239 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
243 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
251 *_challenge = challenge;
262 typedef struct AsyncPolkitQuery {
263 sd_bus_message *request, *reply;
264 sd_bus_message_handler_t callback;
270 static void async_polkit_query_free(AsyncPolkitQuery *q) {
275 sd_bus_slot_unref(q->slot);
277 if (q->registry && q->request)
278 hashmap_remove(q->registry, q->request);
280 sd_bus_message_unref(q->request);
281 sd_bus_message_unref(q->reply);
286 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
287 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
288 AsyncPolkitQuery *q = userdata;
295 q->slot = sd_bus_slot_unref(q->slot);
296 q->reply = sd_bus_message_ref(reply);
298 r = sd_bus_message_rewind(q->request, true);
300 r = sd_bus_reply_method_errno(q->request, r, NULL);
304 r = q->callback(bus, q->request, q->userdata, &error_buffer);
305 r = bus_maybe_reply_error(q->request, r, &error_buffer);
308 async_polkit_query_free(q);
315 int bus_verify_polkit_async(
316 sd_bus_message *call,
321 sd_bus_error *error) {
324 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
327 sd_bus_message_handler_t callback;
337 q = hashmap_get(*registry, call);
339 int authorized, challenge;
341 /* This is the second invocation of this function, and
342 * there's already a response from polkit, let's
346 if (sd_bus_message_is_method_error(q->reply, NULL)) {
347 const sd_bus_error *e;
349 /* Copy error from polkit reply */
350 e = sd_bus_message_get_error(q->reply);
351 sd_bus_error_copy(error, e);
353 /* Treat no PK available as access denied */
354 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
357 return -sd_bus_error_get_errno(e);
360 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
362 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
374 r = sd_bus_query_sender_privilege(call, capability);
381 if (sd_bus_get_current_message(call->bus) != call)
384 callback = sd_bus_get_current_handler(call->bus);
388 userdata = sd_bus_get_current_userdata(call->bus);
390 sender = sd_bus_message_get_sender(call);
394 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
398 r = sd_bus_message_new_method_call(
401 "org.freedesktop.PolicyKit1",
402 "/org/freedesktop/PolicyKit1/Authority",
403 "org.freedesktop.PolicyKit1.Authority",
404 "CheckAuthorization");
408 r = sd_bus_message_append(
411 "system-bus-name", 1, "name", "s", sender,
419 q = new0(AsyncPolkitQuery, 1);
423 q->request = sd_bus_message_ref(call);
424 q->callback = callback;
425 q->userdata = userdata;
427 r = hashmap_put(*registry, call, q);
429 async_polkit_query_free(q);
433 q->registry = *registry;
435 r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
437 async_polkit_query_free(q);
447 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
451 while ((q = hashmap_steal_first(registry)))
452 async_polkit_query_free(q);
454 hashmap_free(registry);
458 int bus_check_peercred(sd_bus *c) {
465 fd = sd_bus_get_fd(c);
469 l = sizeof(struct ucred);
470 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
473 if (l != sizeof(struct ucred))
476 if (ucred.uid != 0 && ucred.uid != geteuid())
482 int bus_open_system_systemd(sd_bus **_bus) {
483 _cleanup_bus_unref_ sd_bus *bus = NULL;
489 return sd_bus_open_system(_bus);
491 /* If we are root and kdbus is not available, then let's talk
492 * directly to the system instance, instead of going via the
496 r = sd_bus_new(&bus);
500 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
504 bus->bus_client = true;
506 r = sd_bus_start(bus);
513 bus = sd_bus_unref(bus);
516 r = sd_bus_new(&bus);
520 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
524 r = sd_bus_start(bus);
526 return sd_bus_open_system(_bus);
528 r = bus_check_peercred(bus);
538 int bus_open_user_systemd(sd_bus **_bus) {
539 _cleanup_bus_unref_ sd_bus *bus = NULL;
540 _cleanup_free_ char *ee = NULL;
544 /* Try via kdbus first, and then directly */
549 r = sd_bus_new(&bus);
553 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
556 bus->bus_client = true;
558 r = sd_bus_start(bus);
565 bus = sd_bus_unref(bus);
568 e = secure_getenv("XDG_RUNTIME_DIR");
570 return sd_bus_open_user(_bus);
572 ee = bus_address_escape(e);
576 r = sd_bus_new(&bus);
580 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
584 r = sd_bus_start(bus);
586 return sd_bus_open_user(_bus);
588 r = bus_check_peercred(bus);
598 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
600 const char *contents;
606 r = sd_bus_message_peek_type(property, &type, &contents);
612 case SD_BUS_TYPE_STRING: {
615 r = sd_bus_message_read_basic(property, type, &s);
619 if (all || !isempty(s))
620 printf("%s=%s\n", name, s);
625 case SD_BUS_TYPE_BOOLEAN: {
628 r = sd_bus_message_read_basic(property, type, &b);
632 printf("%s=%s\n", name, yes_no(b));
637 case SD_BUS_TYPE_UINT64: {
640 r = sd_bus_message_read_basic(property, type, &u);
644 /* Yes, heuristics! But we can change this check
645 * should it turn out to not be sufficient */
647 if (endswith(name, "Timestamp")) {
648 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
650 t = format_timestamp(timestamp, sizeof(timestamp), u);
652 printf("%s=%s\n", name, strempty(t));
654 } else if (strstr(name, "USec")) {
655 char timespan[FORMAT_TIMESPAN_MAX];
657 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
659 printf("%s=%llu\n", name, (unsigned long long) u);
664 case SD_BUS_TYPE_UINT32: {
667 r = sd_bus_message_read_basic(property, type, &u);
671 if (strstr(name, "UMask") || strstr(name, "Mode"))
672 printf("%s=%04o\n", name, u);
674 printf("%s=%u\n", name, (unsigned) u);
679 case SD_BUS_TYPE_INT32: {
682 r = sd_bus_message_read_basic(property, type, &i);
686 printf("%s=%i\n", name, (int) i);
690 case SD_BUS_TYPE_DOUBLE: {
693 r = sd_bus_message_read_basic(property, type, &d);
697 printf("%s=%g\n", name, d);
701 case SD_BUS_TYPE_ARRAY:
702 if (streq(contents, "s")) {
706 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
710 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
714 printf("%s%s", first ? "" : " ", str);
726 r = sd_bus_message_exit_container(property);
732 } else if (streq(contents, "y")) {
736 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
745 for (i = 0; i < n; i++)
746 printf("%02x", u[i]);
753 } else if (streq(contents, "u")) {
757 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
766 for (i = 0; i < n; i++)
767 printf("%08x", u[i]);
781 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
782 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
783 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
789 r = sd_bus_call_method(bus,
792 "org.freedesktop.DBus.Properties",
800 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
804 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
806 const char *contents;
808 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
812 if (!filter || strv_find(filter, name)) {
813 r = sd_bus_message_peek_type(reply, NULL, &contents);
817 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
821 r = bus_print_property(name, reply, all);
826 printf("%s=[unprintable]\n", name);
827 /* skip what we didn't read */
828 r = sd_bus_message_skip(reply, contents);
833 r = sd_bus_message_exit_container(reply);
837 r = sd_bus_message_skip(reply, "v");
842 r = sd_bus_message_exit_container(reply);
849 r = sd_bus_message_exit_container(reply);
856 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
857 sd_id128_t *p = userdata;
862 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
869 memcpy((*p).bytes, v, n);
876 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
880 r = sd_bus_message_peek_type(m, &type, NULL);
885 case SD_BUS_TYPE_STRING: {
890 r = sd_bus_message_read_basic(m, type, &s);
908 case SD_BUS_TYPE_ARRAY: {
909 _cleanup_strv_free_ char **l = NULL;
910 char ***p = userdata;
912 r = bus_message_read_strv_extend(m, &l);
923 case SD_BUS_TYPE_BOOLEAN: {
927 r = sd_bus_message_read_basic(m, type, &b);
936 case SD_BUS_TYPE_UINT32: {
938 uint32_t *p = userdata;
940 r = sd_bus_message_read_basic(m, type, &u);
949 case SD_BUS_TYPE_UINT64: {
951 uint64_t *p = userdata;
953 r = sd_bus_message_read_basic(m, type, &t);
969 int bus_map_all_properties(sd_bus *bus,
970 const char *destination,
972 const struct bus_properties_map *map,
974 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
975 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
983 r = sd_bus_call_method(
987 "org.freedesktop.DBus.Properties",
995 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
999 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1000 const struct bus_properties_map *prop;
1002 const char *contents;
1006 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1010 for (i = 0, prop = NULL; map[i].member; i++)
1011 if (streq(map[i].member, member)) {
1017 r = sd_bus_message_peek_type(m, NULL, &contents);
1021 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1025 v = (uint8_t *)userdata + prop->offset;
1027 r = prop->set(bus, member, m, &error, v);
1029 r = map_basic(bus, member, m, &error, v);
1033 r = sd_bus_message_exit_container(m);
1037 r = sd_bus_message_skip(m, "v");
1042 r = sd_bus_message_exit_container(m);
1050 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1053 assert(transport >= 0);
1054 assert(transport < _BUS_TRANSPORT_MAX);
1057 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1058 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1060 switch (transport) {
1062 case BUS_TRANSPORT_LOCAL:
1064 r = sd_bus_default_user(bus);
1066 r = sd_bus_default_system(bus);
1070 case BUS_TRANSPORT_REMOTE:
1071 r = sd_bus_open_system_remote(bus, host);
1074 case BUS_TRANSPORT_CONTAINER:
1075 r = sd_bus_open_system_container(bus, host);
1079 assert_not_reached("Hmm, unknown transport type.");
1085 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1088 assert(transport >= 0);
1089 assert(transport < _BUS_TRANSPORT_MAX);
1092 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1093 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1095 switch (transport) {
1097 case BUS_TRANSPORT_LOCAL:
1099 r = bus_open_user_systemd(bus);
1101 r = bus_open_system_systemd(bus);
1105 case BUS_TRANSPORT_REMOTE:
1106 r = sd_bus_open_system_remote(bus, host);
1109 case BUS_TRANSPORT_CONTAINER:
1110 r = sd_bus_open_system_container(bus, host);
1114 assert_not_reached("Hmm, unknown transport type.");
1120 int bus_property_get_bool(
1123 const char *interface,
1124 const char *property,
1125 sd_bus_message *reply,
1127 sd_bus_error *error) {
1129 int b = *(bool*) userdata;
1131 return sd_bus_message_append_basic(reply, 'b', &b);
1134 #if __SIZEOF_SIZE_T__ != 8
1135 int bus_property_get_size(
1138 const char *interface,
1139 const char *property,
1140 sd_bus_message *reply,
1142 sd_bus_error *error) {
1144 uint64_t sz = *(size_t*) userdata;
1146 return sd_bus_message_append_basic(reply, 't', &sz);
1150 #if __SIZEOF_LONG__ != 8
1151 int bus_property_get_long(
1154 const char *interface,
1155 const char *property,
1156 sd_bus_message *reply,
1158 sd_bus_error *error) {
1160 int64_t l = *(long*) userdata;
1162 return sd_bus_message_append_basic(reply, 'x', &l);
1165 int bus_property_get_ulong(
1168 const char *interface,
1169 const char *property,
1170 sd_bus_message *reply,
1172 sd_bus_error *error) {
1174 uint64_t ul = *(unsigned long*) userdata;
1176 return sd_bus_message_append_basic(reply, 't', &ul);
1180 int bus_log_parse_error(int r) {
1181 log_error("Failed to parse bus message: %s", strerror(-r));
1185 int bus_log_create_error(int r) {
1186 log_error("Failed to create bus message: %s", strerror(-r));
1190 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1196 return sd_bus_message_read(
1211 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1215 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1216 sd_bus_reply_method_errno(m, r, error);
1218 } else if (sd_bus_error_is_set(error)) {
1219 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1220 sd_bus_reply_method_error(m, error);
1224 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1225 bus_message_type_to_string(m->header->type),
1228 strna(m->interface),
1230 strna(m->root_container.signature),
1231 bus_error_message(error, r));
1236 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1237 const char *eq, *field;
1243 eq = strchr(assignment, '=');
1245 log_error("Not an assignment: %s", assignment);
1249 field = strndupa(assignment, eq - assignment);
1252 if (streq(field, "CPUQuota")) {
1256 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1258 return bus_log_create_error(r);
1260 r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1262 } else if (endswith(eq, "%")) {
1265 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1266 log_error("CPU quota '%s' invalid.", eq);
1270 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1272 return bus_log_create_error(r);
1274 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1276 log_error("CPU quota needs to be in percent.");
1281 return bus_log_create_error(r);
1286 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1288 return bus_log_create_error(r);
1290 if (STR_IN_SET(field,
1291 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1292 "SendSIGHUP", "SendSIGKILL")) {
1294 r = parse_boolean(eq);
1296 log_error("Failed to parse boolean assignment %s.", assignment);
1300 r = sd_bus_message_append(m, "v", "b", r);
1302 } else if (streq(field, "MemoryLimit")) {
1305 r = parse_size(eq, 1024, &bytes);
1307 log_error("Failed to parse bytes specification %s", assignment);
1311 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1313 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1316 r = safe_atou64(eq, &u);
1318 log_error("Failed to parse %s value %s.", field, eq);
1322 r = sd_bus_message_append(m, "v", "t", u);
1324 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1325 r = sd_bus_message_append(m, "v", "s", eq);
1327 else if (streq(field, "DeviceAllow")) {
1330 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1332 const char *path, *rwm, *e;
1334 e = strchr(eq, ' ');
1336 path = strndupa(eq, e - eq);
1343 if (!path_startswith(path, "/dev")) {
1344 log_error("%s is not a device file in /dev.", path);
1348 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1351 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1354 r = sd_bus_message_append(m, "v", "a(st)", 0);
1356 const char *path, *bandwidth, *e;
1359 e = strchr(eq, ' ');
1361 path = strndupa(eq, e - eq);
1364 log_error("Failed to parse %s value %s.", field, eq);
1368 if (!path_startswith(path, "/dev")) {
1369 log_error("%s is not a device file in /dev.", path);
1373 r = parse_size(bandwidth, 1000, &bytes);
1375 log_error("Failed to parse byte value %s.", bandwidth);
1379 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1382 } else if (streq(field, "BlockIODeviceWeight")) {
1385 r = sd_bus_message_append(m, "v", "a(st)", 0);
1387 const char *path, *weight, *e;
1390 e = strchr(eq, ' ');
1392 path = strndupa(eq, e - eq);
1395 log_error("Failed to parse %s value %s.", field, eq);
1399 if (!path_startswith(path, "/dev")) {
1400 log_error("%s is not a device file in /dev.", path);
1404 r = safe_atou64(weight, &u);
1406 log_error("Failed to parse %s value %s.", field, weight);
1409 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1412 } else if (rlimit_from_string(field) >= 0) {
1415 if (streq(eq, "infinity"))
1418 r = safe_atou64(eq, &rl);
1420 log_error("Invalid resource limit: %s", eq);
1425 r = sd_bus_message_append(m, "v", "t", rl);
1427 } else if (streq(field, "Nice")) {
1430 r = safe_atoi32(eq, &i);
1432 log_error("Failed to parse %s value %s.", field, eq);
1436 r = sd_bus_message_append(m, "v", "i", i);
1438 } else if (streq(field, "Environment")) {
1440 r = sd_bus_message_append(m, "v", "as", 1, eq);
1442 } else if (streq(field, "KillSignal")) {
1445 sig = signal_from_string_try_harder(eq);
1447 log_error("Failed to parse %s value %s.", field, eq);
1451 r = sd_bus_message_append(m, "v", "i", sig);
1454 log_error("Unknown assignment %s.", assignment);
1459 return bus_log_create_error(r);