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(
194 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
202 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
206 r = sd_bus_creds_get_uid(creds, &uid);
215 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
216 int authorized = false, challenge = false;
219 sender = sd_bus_message_get_sender(m);
223 r = sd_bus_call_method(
225 "org.freedesktop.PolicyKit1",
226 "/org/freedesktop/PolicyKit1/Authority",
227 "org.freedesktop.PolicyKit1.Authority",
228 "CheckAuthorization",
232 "system-bus-name", 1, "name", "s", sender,
239 /* Treat no PK available as access denied */
240 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
241 sd_bus_error_free(e);
248 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
252 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
260 *_challenge = challenge;
271 typedef struct AsyncPolkitQuery {
272 sd_bus_message *request, *reply;
273 sd_bus_message_handler_t callback;
279 static void async_polkit_query_free(AsyncPolkitQuery *q) {
284 sd_bus_slot_unref(q->slot);
286 if (q->registry && q->request)
287 hashmap_remove(q->registry, q->request);
289 sd_bus_message_unref(q->request);
290 sd_bus_message_unref(q->reply);
295 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
296 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
297 AsyncPolkitQuery *q = userdata;
304 q->slot = sd_bus_slot_unref(q->slot);
305 q->reply = sd_bus_message_ref(reply);
307 r = sd_bus_message_rewind(q->request, true);
309 r = sd_bus_reply_method_errno(q->request, r, NULL);
313 r = q->callback(bus, q->request, q->userdata, &error_buffer);
314 r = bus_maybe_reply_error(q->request, r, &error_buffer);
317 async_polkit_query_free(q);
324 int bus_verify_polkit_async(
331 sd_bus_message_handler_t callback,
335 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
339 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
349 q = hashmap_get(*registry, m);
351 int authorized, challenge;
353 /* This is the second invocation of this function, and
354 * there's already a response from polkit, let's
358 if (sd_bus_message_is_method_error(q->reply, NULL)) {
359 const sd_bus_error *e;
361 /* Copy error from polkit reply */
362 e = sd_bus_message_get_error(q->reply);
363 sd_bus_error_copy(error, e);
365 /* Treat no PK available as access denied */
366 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
369 return -sd_bus_error_get_errno(e);
372 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
374 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
386 r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds);
390 r = sd_bus_creds_get_uid(creds, &uid);
398 sender = sd_bus_message_get_sender(m);
402 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
406 r = sd_bus_message_new_method_call(
409 "org.freedesktop.PolicyKit1",
410 "/org/freedesktop/PolicyKit1/Authority",
411 "org.freedesktop.PolicyKit1.Authority",
412 "CheckAuthorization");
416 r = sd_bus_message_append(
419 "system-bus-name", 1, "name", "s", sender,
427 q = new0(AsyncPolkitQuery, 1);
431 q->request = sd_bus_message_ref(m);
432 q->callback = callback;
433 q->userdata = userdata;
435 r = hashmap_put(*registry, m, q);
437 async_polkit_query_free(q);
441 q->registry = *registry;
443 r = sd_bus_call_async(bus, &q->slot, pk, async_polkit_callback, q, 0);
445 async_polkit_query_free(q);
455 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
459 while ((q = hashmap_steal_first(registry)))
460 async_polkit_query_free(q);
462 hashmap_free(registry);
466 int bus_check_peercred(sd_bus *c) {
473 fd = sd_bus_get_fd(c);
477 l = sizeof(struct ucred);
478 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
481 if (l != sizeof(struct ucred))
484 if (ucred.uid != 0 && ucred.uid != geteuid())
490 int bus_open_system_systemd(sd_bus **_bus) {
491 _cleanup_bus_unref_ sd_bus *bus = NULL;
497 return sd_bus_open_system(_bus);
499 /* If we are root and kdbus is not available, then let's talk
500 * directly to the system instance, instead of going via the
504 r = sd_bus_new(&bus);
508 r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_PATH);
512 bus->bus_client = true;
514 r = sd_bus_start(bus);
521 bus = sd_bus_unref(bus);
524 r = sd_bus_new(&bus);
528 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
532 r = sd_bus_start(bus);
534 return sd_bus_open_system(_bus);
536 r = bus_check_peercred(bus);
546 int bus_open_user_systemd(sd_bus **_bus) {
547 _cleanup_bus_unref_ sd_bus *bus = NULL;
548 _cleanup_free_ char *ee = NULL;
552 /* Try via kdbus first, and then directly */
557 r = sd_bus_new(&bus);
561 if (asprintf(&bus->address, KERNEL_USER_BUS_FMT, getuid()) < 0)
564 bus->bus_client = true;
566 r = sd_bus_start(bus);
573 bus = sd_bus_unref(bus);
576 e = secure_getenv("XDG_RUNTIME_DIR");
578 return sd_bus_open_user(_bus);
580 ee = bus_address_escape(e);
584 r = sd_bus_new(&bus);
588 bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
592 r = sd_bus_start(bus);
594 return sd_bus_open_user(_bus);
596 r = bus_check_peercred(bus);
606 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
608 const char *contents;
614 r = sd_bus_message_peek_type(property, &type, &contents);
620 case SD_BUS_TYPE_STRING: {
623 r = sd_bus_message_read_basic(property, type, &s);
627 if (all || !isempty(s))
628 printf("%s=%s\n", name, s);
633 case SD_BUS_TYPE_BOOLEAN: {
636 r = sd_bus_message_read_basic(property, type, &b);
640 printf("%s=%s\n", name, yes_no(b));
645 case SD_BUS_TYPE_UINT64: {
648 r = sd_bus_message_read_basic(property, type, &u);
652 /* Yes, heuristics! But we can change this check
653 * should it turn out to not be sufficient */
655 if (endswith(name, "Timestamp")) {
656 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
658 t = format_timestamp(timestamp, sizeof(timestamp), u);
660 printf("%s=%s\n", name, strempty(t));
662 } else if (strstr(name, "USec")) {
663 char timespan[FORMAT_TIMESPAN_MAX];
665 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
667 printf("%s=%llu\n", name, (unsigned long long) u);
672 case SD_BUS_TYPE_UINT32: {
675 r = sd_bus_message_read_basic(property, type, &u);
679 if (strstr(name, "UMask") || strstr(name, "Mode"))
680 printf("%s=%04o\n", name, u);
682 printf("%s=%u\n", name, (unsigned) u);
687 case SD_BUS_TYPE_INT32: {
690 r = sd_bus_message_read_basic(property, type, &i);
694 printf("%s=%i\n", name, (int) i);
698 case SD_BUS_TYPE_DOUBLE: {
701 r = sd_bus_message_read_basic(property, type, &d);
705 printf("%s=%g\n", name, d);
709 case SD_BUS_TYPE_ARRAY:
710 if (streq(contents, "s")) {
714 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
718 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
722 printf("%s%s", first ? "" : " ", str);
734 r = sd_bus_message_exit_container(property);
740 } else if (streq(contents, "y")) {
744 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
753 for (i = 0; i < n; i++)
754 printf("%02x", u[i]);
761 } else if (streq(contents, "u")) {
765 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
774 for (i = 0; i < n; i++)
775 printf("%08x", u[i]);
789 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
790 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
791 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
797 r = sd_bus_call_method(bus,
800 "org.freedesktop.DBus.Properties",
808 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
812 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
814 const char *contents;
816 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
820 if (!filter || strv_find(filter, name)) {
821 r = sd_bus_message_peek_type(reply, NULL, &contents);
825 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
829 r = bus_print_property(name, reply, all);
834 printf("%s=[unprintable]\n", name);
835 /* skip what we didn't read */
836 r = sd_bus_message_skip(reply, contents);
841 r = sd_bus_message_exit_container(reply);
845 r = sd_bus_message_skip(reply, "v");
850 r = sd_bus_message_exit_container(reply);
857 r = sd_bus_message_exit_container(reply);
864 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
865 sd_id128_t *p = userdata;
870 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
877 memcpy((*p).bytes, v, n);
884 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
888 r = sd_bus_message_peek_type(m, &type, NULL);
893 case SD_BUS_TYPE_STRING: {
898 r = sd_bus_message_read_basic(m, type, &s);
916 case SD_BUS_TYPE_ARRAY: {
917 _cleanup_strv_free_ char **l = NULL;
918 char ***p = userdata;
920 r = bus_message_read_strv_extend(m, &l);
931 case SD_BUS_TYPE_BOOLEAN: {
935 r = sd_bus_message_read_basic(m, type, &b);
944 case SD_BUS_TYPE_UINT32: {
946 uint32_t *p = userdata;
948 r = sd_bus_message_read_basic(m, type, &u);
957 case SD_BUS_TYPE_UINT64: {
959 uint64_t *p = userdata;
961 r = sd_bus_message_read_basic(m, type, &t);
977 int bus_map_all_properties(sd_bus *bus,
978 const char *destination,
980 const struct bus_properties_map *map,
982 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
983 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
991 r = sd_bus_call_method(
995 "org.freedesktop.DBus.Properties",
1003 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1007 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1008 const struct bus_properties_map *prop;
1010 const char *contents;
1014 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1018 for (i = 0, prop = NULL; map[i].member; i++)
1019 if (streq(map[i].member, member)) {
1025 r = sd_bus_message_peek_type(m, NULL, &contents);
1029 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1033 v = (uint8_t *)userdata + prop->offset;
1035 r = prop->set(bus, member, m, &error, v);
1037 r = map_basic(bus, member, m, &error, v);
1041 r = sd_bus_message_exit_container(m);
1045 r = sd_bus_message_skip(m, "v");
1050 r = sd_bus_message_exit_container(m);
1058 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1061 assert(transport >= 0);
1062 assert(transport < _BUS_TRANSPORT_MAX);
1065 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1066 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1068 switch (transport) {
1070 case BUS_TRANSPORT_LOCAL:
1072 r = sd_bus_default_user(bus);
1074 r = sd_bus_default_system(bus);
1078 case BUS_TRANSPORT_REMOTE:
1079 r = sd_bus_open_system_remote(bus, host);
1082 case BUS_TRANSPORT_CONTAINER:
1083 r = sd_bus_open_system_container(bus, host);
1087 assert_not_reached("Hmm, unknown transport type.");
1093 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1096 assert(transport >= 0);
1097 assert(transport < _BUS_TRANSPORT_MAX);
1100 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1101 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1103 switch (transport) {
1105 case BUS_TRANSPORT_LOCAL:
1107 r = bus_open_user_systemd(bus);
1109 r = bus_open_system_systemd(bus);
1113 case BUS_TRANSPORT_REMOTE:
1114 r = sd_bus_open_system_remote(bus, host);
1117 case BUS_TRANSPORT_CONTAINER:
1118 r = sd_bus_open_system_container(bus, host);
1122 assert_not_reached("Hmm, unknown transport type.");
1128 int bus_property_get_bool(
1131 const char *interface,
1132 const char *property,
1133 sd_bus_message *reply,
1135 sd_bus_error *error) {
1137 int b = *(bool*) userdata;
1139 return sd_bus_message_append_basic(reply, 'b', &b);
1142 #if __SIZEOF_SIZE_T__ != 8
1143 int bus_property_get_size(
1146 const char *interface,
1147 const char *property,
1148 sd_bus_message *reply,
1150 sd_bus_error *error) {
1152 uint64_t sz = *(size_t*) userdata;
1154 return sd_bus_message_append_basic(reply, 't', &sz);
1158 #if __SIZEOF_LONG__ != 8
1159 int bus_property_get_long(
1162 const char *interface,
1163 const char *property,
1164 sd_bus_message *reply,
1166 sd_bus_error *error) {
1168 int64_t l = *(long*) userdata;
1170 return sd_bus_message_append_basic(reply, 'x', &l);
1173 int bus_property_get_ulong(
1176 const char *interface,
1177 const char *property,
1178 sd_bus_message *reply,
1180 sd_bus_error *error) {
1182 uint64_t ul = *(unsigned long*) userdata;
1184 return sd_bus_message_append_basic(reply, 't', &ul);
1188 int bus_log_parse_error(int r) {
1189 log_error("Failed to parse message: %s", strerror(-r));
1193 int bus_log_create_error(int r) {
1194 log_error("Failed to create message: %s", strerror(-r));
1198 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1204 return sd_bus_message_read(
1219 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1223 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1224 sd_bus_reply_method_errno(m, r, error);
1226 } else if (sd_bus_error_is_set(error)) {
1227 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1228 sd_bus_reply_method_error(m, error);
1232 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1233 bus_message_type_to_string(m->header->type),
1236 strna(m->interface),
1238 strna(m->root_container.signature),
1239 bus_error_message(error, r));
1244 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1245 const char *eq, *field;
1251 eq = strchr(assignment, '=');
1253 log_error("Not an assignment: %s", assignment);
1257 field = strndupa(assignment, eq - assignment);
1260 if (streq(field, "CPUQuota")) {
1264 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1266 return bus_log_create_error(r);
1268 r = sd_bus_message_append(m, "v", "t", (usec_t) -1);
1270 } else if (endswith(eq, "%")) {
1273 if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1274 log_error("CPU quota '%s' invalid.", eq);
1278 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1280 return bus_log_create_error(r);
1282 r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1284 log_error("CPU quota needs to be in percent.");
1289 return bus_log_create_error(r);
1294 r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1296 return bus_log_create_error(r);
1298 if (STR_IN_SET(field,
1299 "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1300 "SendSIGHUP", "SendSIGKILL")) {
1302 r = parse_boolean(eq);
1304 log_error("Failed to parse boolean assignment %s.", assignment);
1308 r = sd_bus_message_append(m, "v", "b", r);
1310 } else if (streq(field, "MemoryLimit")) {
1313 r = parse_size(eq, 1024, &bytes);
1315 log_error("Failed to parse bytes specification %s", assignment);
1319 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1321 } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1324 r = safe_atou64(eq, &u);
1326 log_error("Failed to parse %s value %s.", field, eq);
1330 r = sd_bus_message_append(m, "v", "t", u);
1332 } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1333 r = sd_bus_message_append(m, "v", "s", eq);
1335 else if (streq(field, "DeviceAllow")) {
1338 r = sd_bus_message_append(m, "v", "a(ss)", 0);
1340 const char *path, *rwm, *e;
1342 e = strchr(eq, ' ');
1344 path = strndupa(eq, e - eq);
1351 if (!path_startswith(path, "/dev")) {
1352 log_error("%s is not a device file in /dev.", path);
1356 r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1359 } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1362 r = sd_bus_message_append(m, "v", "a(st)", 0);
1364 const char *path, *bandwidth, *e;
1367 e = strchr(eq, ' ');
1369 path = strndupa(eq, e - eq);
1372 log_error("Failed to parse %s value %s.", field, eq);
1376 if (!path_startswith(path, "/dev")) {
1377 log_error("%s is not a device file in /dev.", path);
1381 r = parse_size(bandwidth, 1000, &bytes);
1383 log_error("Failed to parse byte value %s.", bandwidth);
1387 r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1390 } else if (streq(field, "BlockIODeviceWeight")) {
1393 r = sd_bus_message_append(m, "v", "a(st)", 0);
1395 const char *path, *weight, *e;
1398 e = strchr(eq, ' ');
1400 path = strndupa(eq, e - eq);
1403 log_error("Failed to parse %s value %s.", field, eq);
1407 if (!path_startswith(path, "/dev")) {
1408 log_error("%s is not a device file in /dev.", path);
1412 r = safe_atou64(weight, &u);
1414 log_error("Failed to parse %s value %s.", field, weight);
1417 r = sd_bus_message_append(m, "v", "a(st)", path, u);
1420 } else if (rlimit_from_string(field) >= 0) {
1423 if (streq(eq, "infinity"))
1426 r = safe_atou64(eq, &rl);
1428 log_error("Invalid resource limit: %s", eq);
1433 r = sd_bus_message_append(m, "v", "t", rl);
1435 } else if (streq(field, "Nice")) {
1438 r = safe_atoi32(eq, &i);
1440 log_error("Failed to parse %s value %s.", field, eq);
1444 r = sd_bus_message_append(m, "v", "i", i);
1446 } else if (streq(field, "Environment")) {
1448 r = sd_bus_message_append(m, "v", "as", 1, eq);
1450 } else if (streq(field, "KillSignal")) {
1453 sig = signal_from_string_try_harder(eq);
1455 log_error("Failed to parse %s value %s.", field, eq);
1459 r = sd_bus_message_append(m, "v", "i", sig);
1462 log_error("Unknown assignment %s.", assignment);
1467 return bus_log_create_error(r);