X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Fbus-util.c;h=800657ccde18a21d2ed566a57f0c6c11f6819f93;hp=1e80ebcf6cef918fc5eb73ef45f464dbe43feafc;hb=39be55bb38f955a837a09bbedc2b7c67b6d6f3e3;hpb=d76bb3c179b7a32b109e39aa87ff09c8f5a8c178 diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 1e80ebcf6..800657ccd 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,29 +17,58 @@ along with systemd; If not, see . ***/ -// #include - -// #include "sd-daemon.h" -// #include "sd-event.h" -// #include "util.h" -#include "strv.h" -// #include "macro.h" -// #include "def.h" -// #include "path-util.h" -// #include "missing.h" -// #include "set.h" -// #include "signal-util.h" -#include "unit-name.h" - -// #include "sd-bus.h" -// #include "bus-error.h" -// #include "bus-label.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sd-bus-protocol.h" +#include "sd-bus.h" +#include "sd-daemon.h" +#include "sd-event.h" +#include "sd-id128.h" + +#include "alloc-util.h" +#include "bus-internal.h" +#include "bus-label.h" #include "bus-message.h" #include "bus-util.h" -#include "bus-internal.h" +#include "cgroup-util.h" +#include "def.h" +//#include "env-util.h" +#include "escape.h" +#include "extract-word.h" +#include "fd-util.h" +#include "hashmap.h" +//#include "install.h" +#include "kdbus.h" +#include "log.h" +#include "macro.h" +#include "missing.h" +#include "parse-util.h" +#include "path-util.h" +#include "proc-cmdline.h" +#include "process-util.h" +//#include "rlimit-util.h" +#include "set.h" +#include "signal-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "syslog-util.h" +#include "time-util.h" +#include "unit-name.h" +#include "user-util.h" +#include "utf8.h" +#include "util.h" -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { sd_event *e = userdata; @@ -170,7 +197,7 @@ int bus_event_loop_with_idle( #endif // 0 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { - _cleanup_bus_message_unref_ sd_bus_message *rep = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL; int r, has_owner = 0; assert(c); @@ -196,7 +223,7 @@ int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { } static int check_good_user(sd_bus_message *m, uid_t good_user) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t sender_uid; int r; @@ -246,8 +273,8 @@ int bus_test_polkit( return 1; #ifdef ENABLE_POLKIT else { - _cleanup_bus_message_unref_ sd_bus_message *request = NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; int authorized = false, challenge = false; const char *sender, **k, **v; @@ -350,7 +377,7 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { } static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { - _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; AsyncPolkitQuery *q = userdata; int r; @@ -388,7 +415,7 @@ int bus_verify_polkit_async( sd_bus_error *error) { #ifdef ENABLE_POLKIT - _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; AsyncPolkitQuery *q; const char *sender, **k, **v; sd_bus_message_handler_t callback; @@ -551,8 +578,7 @@ void bus_verify_polkit_async_registry_free(Hashmap *registry) { #endif } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int bus_check_peercred(sd_bus *c) { struct ucred ucred; socklen_t l; @@ -577,14 +603,14 @@ int bus_check_peercred(sd_bus *c) { return 1; } -int bus_open_system_systemd(sd_bus **_bus) { - _cleanup_bus_unref_ sd_bus *bus = NULL; +int bus_connect_system_systemd(sd_bus **_bus) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; int r; assert(_bus); if (geteuid() != 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); /* If we are root and kdbus is not available, then let's talk * directly to the system instance, instead of going via the @@ -619,7 +645,7 @@ int bus_open_system_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_system(_bus); + return sd_bus_default_system(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -631,8 +657,8 @@ int bus_open_system_systemd(sd_bus **_bus) { return 0; } -int bus_open_user_systemd(sd_bus **_bus) { - _cleanup_bus_unref_ sd_bus *bus = NULL; +int bus_connect_user_systemd(sd_bus **_bus) { + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; _cleanup_free_ char *ee = NULL; const char *e; int r; @@ -661,7 +687,7 @@ int bus_open_user_systemd(sd_bus **_bus) { e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); ee = bus_address_escape(e); if (!ee) @@ -677,7 +703,7 @@ int bus_open_user_systemd(sd_bus **_bus) { r = sd_bus_start(bus); if (r < 0) - return sd_bus_open_user(_bus); + return sd_bus_default_user(_bus); r = bus_check_peercred(bus); if (r < 0) @@ -821,7 +847,7 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { if (r < 0) return r; - while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { + while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) { _cleanup_free_ char *escaped = NULL; if (first) @@ -899,8 +925,8 @@ int bus_print_property(const char *name, sd_bus_message *property, bool all) { } int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -1046,7 +1072,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_ } case SD_BUS_TYPE_UINT32: { - uint64_t u; + uint32_t u; uint32_t *p = userdata; r = sd_bus_message_read_basic(m, type, &u); @@ -1083,7 +1109,7 @@ int bus_message_map_all_properties( const struct bus_properties_map *map, void *userdata) { - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(m); @@ -1146,8 +1172,7 @@ int bus_message_map_all_properties( return sd_bus_message_exit_container(m); } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int bus_message_map_properties_changed( sd_bus_message *m, const struct bus_properties_map *map, @@ -1192,8 +1217,8 @@ int bus_map_all_properties( const struct bus_properties_map *map, void *userdata) { - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; - _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; assert(bus); @@ -1216,7 +1241,7 @@ int bus_map_all_properties( return bus_message_map_all_properties(m, map, userdata); } -int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { +int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1229,8 +1254,7 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b switch (transport) { case BUS_TRANSPORT_LOCAL: -/// elogind does not support a user bus -#if 0 +#if 0 /// elogind does not support a user bus if (user) r = sd_bus_default_user(bus); else @@ -1254,9 +1278,8 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b return r; } -/// UNNEEDED by elogind -#if 0 -int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { +#if 0 /// UNNEEDED by elogind +int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; assert(transport >= 0); @@ -1270,9 +1293,9 @@ int bus_open_transport_systemd(BusTransport transport, const char *host, bool us case BUS_TRANSPORT_LOCAL: if (user) - r = bus_open_user_systemd(bus); + r = bus_connect_user_systemd(bus); else - r = bus_open_system_systemd(bus); + r = bus_connect_system_systemd(bus); break; @@ -1356,8 +1379,7 @@ int bus_log_parse_error(int r) { return log_error_errno(r, "Failed to parse bus message: %m"); } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int bus_log_create_error(int r) { return log_error_errno(r, "Failed to create bus message: %m"); } @@ -1385,7 +1407,7 @@ int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) { int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) { const char *eq, *field; - int r; + int r, rl; assert(m); assert(assignment); @@ -1396,20 +1418,18 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return -EINVAL; } + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + field = strndupa(assignment, eq - assignment); - eq ++; + eq++; if (streq(field, "CPUQuota")) { - if (isempty(eq)) { - - r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "v", "t", USEC_INFINITY); - - } else if (endswith(eq, "%")) { + if (isempty(eq)) + r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); + else if (endswith(eq, "%")) { double percent; if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) { @@ -1417,54 +1437,126 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return -EINVAL; } - r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec"); - if (r < 0) - return bus_log_create_error(r); - - r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100); + r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100); } else { log_error("CPU quota needs to be in percent."); return -EINVAL; } + goto finish; + + } else if (streq(field, "EnvironmentFile")) { + + r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1, + eq[0] == '-' ? eq + 1 : eq, + eq[0] == '-'); + goto finish; + + } else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec", "RuntimeMaxSec")) { + char *n; + usec_t t; + size_t l; + r = parse_sec(eq, &t); if (r < 0) - return bus_log_create_error(r); + return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq); - return 0; + l = strlen(field); + n = newa(char, l + 2); + if (!n) + return log_oom(); + + /* Change suffix Sec → USec */ + strcpy(mempcpy(n, field, l - 3), "USec"); + r = sd_bus_message_append(m, "sv", n, "t", t); + goto finish; } r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); if (r < 0) return bus_log_create_error(r); - if (STR_IN_SET(field, - "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", + rl = rlimit_from_string(field); + if (rl >= 0) { + const char *sn; + struct rlimit l; + + r = rlimit_parse(rl, eq, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit: %s", eq); + + r = sd_bus_message_append(m, "v", "t", l.rlim_max); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv"); + if (r < 0) + return bus_log_create_error(r); + + sn = strjoina(field, "Soft"); + r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur); + + } else if (STR_IN_SET(field, + "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", - "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit")) { + "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", + "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges", + "SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) { r = parse_boolean(eq); - if (r < 0) { - log_error("Failed to parse boolean assignment %s.", assignment); - return -EINVAL; - } + if (r < 0) + return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment); r = sd_bus_message_append(m, "v", "b", r); } else if (streq(field, "MemoryLimit")) { - off_t bytes; + uint64_t bytes; + if (isempty(eq) || streq(eq, "infinity")) + bytes = (uint64_t) -1; + else { r = parse_size(eq, 1024, &bytes); if (r < 0) { log_error("Failed to parse bytes specification %s", assignment); return -EINVAL; } + } + + r = sd_bus_message_append(m, "v", "t", bytes); + + } else if (streq(field, "TasksMax")) { + uint64_t n; + + if (isempty(eq) || streq(eq, "infinity")) + n = (uint64_t) -1; + else { + r = safe_atou64(eq, &n); + if (r < 0) { + log_error("Failed to parse maximum tasks specification %s", assignment); + return -EINVAL; + } + } + + r = sd_bus_message_append(m, "v", "t", n); + + } else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) { + uint64_t u; + + r = cg_cpu_shares_parse(eq, &u); + if (r < 0) { + log_error("Failed to parse %s value %s.", field, eq); + return -EINVAL; + } - r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes); + r = sd_bus_message_append(m, "v", "t", u); - } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) { + } else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) { uint64_t u; - r = safe_atou64(eq, &u); + r = cg_cpu_shares_parse(eq, &u); if (r < 0) { log_error("Failed to parse %s value %s.", field, eq); return -EINVAL; @@ -1476,10 +1568,34 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "User", "Group", "DevicePolicy", "KillMode", "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath", "StandardInput", "StandardOutput", "StandardError", - "Description", "Slice", "Type")) + "Description", "Slice", "Type", "WorkingDirectory", + "RootDirectory", "SyslogIdentifier", "ProtectSystem", + "ProtectHome")) r = sd_bus_message_append(m, "v", "s", eq); - else if (streq(field, "DeviceAllow")) { + else if (streq(field, "SyslogLevel")) { + int level; + + level = log_level_from_string(eq); + if (level < 0) { + log_error("Failed to parse %s value %s.", field, eq); + return -EINVAL; + } + + r = sd_bus_message_append(m, "v", "i", level); + + } else if (streq(field, "SyslogFacility")) { + int facility; + + facility = log_facility_unshifted_from_string(eq); + if (facility < 0) { + log_error("Failed to parse %s value %s.", field, eq); + return -EINVAL; + } + + r = sd_bus_message_append(m, "v", "i", facility); + + } else if (streq(field, "DeviceAllow")) { if (isempty(eq)) r = sd_bus_message_append(m, "v", "a(ss)", 0); @@ -1509,7 +1625,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "a(st)", 0); else { const char *path, *bandwidth, *e; - off_t bytes; + uint64_t bytes; e = strchr(eq, ' '); if (e) { @@ -1531,7 +1647,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return -EINVAL; } - r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes); + r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes); } } else if (streq(field, "BlockIODeviceWeight")) { @@ -1564,21 +1680,6 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "a(st)", path, u); } - } else if (rlimit_from_string(field) >= 0) { - uint64_t rl; - - if (streq(eq, "infinity")) - rl = (uint64_t) -1; - else { - r = safe_atou64(eq, &rl); - if (r < 0) { - log_error("Invalid resource limit: %s", eq); - return -EINVAL; - } - } - - r = sd_bus_message_append(m, "v", "t", rl); - } else if (streq(field, "Nice")) { int32_t i; @@ -1590,9 +1691,52 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "i", i); - } else if (streq(field, "Environment")) { + } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) { + const char *p; + + r = sd_bus_message_open_container(m, 'v', "as"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + p = eq; - r = sd_bus_message_append(m, "v", "as", 1, eq); + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE); + if (r < 0) { + log_error("Failed to parse Environment value %s", eq); + return -EINVAL; + } + if (r == 0) + break; + + if (streq(field, "Environment")) { + if (!env_assignment_is_valid(word)) { + log_error("Invalid environment assignment: %s", word); + return -EINVAL; + } + } else { /* PassEnvironment */ + if (!env_name_is_valid(word)) { + log_error("Invalid environment variable name: %s", word); + return -EINVAL; + } + } + + r = sd_bus_message_append_basic(m, 's', word); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); } else if (streq(field, "KillSignal")) { int sig; @@ -1605,22 +1749,124 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "i", sig); - } else if (streq(field, "AccuracySec")) { - usec_t u; + } else if (streq(field, "TimerSlackNSec")) { + nsec_t n; - r = parse_sec(eq, &u); + r = parse_nsec(eq, &n); if (r < 0) { log_error("Failed to parse %s value %s", field, eq); return -EINVAL; } - r = sd_bus_message_append(m, "v", "t", u); + r = sd_bus_message_append(m, "v", "t", n); + } else if (streq(field, "OOMScoreAdjust")) { + int oa; + + r = safe_atoi(eq, &oa); + if (r < 0) { + log_error("Failed to parse %s value %s", field, eq); + return -EINVAL; + } + + if (!oom_score_adjust_is_valid(oa)) { + log_error("OOM score adjust value out of range"); + return -EINVAL; + } + + r = sd_bus_message_append(m, "v", "i", oa); + } else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) { + const char *p; + + r = sd_bus_message_open_container(m, 'v', "as"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + p = eq; + + for (;;) { + _cleanup_free_ char *word = NULL; + int offset; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); + if (r < 0) { + log_error("Failed to parse %s value %s", field, eq); + return -EINVAL; + } + if (r == 0) + break; + + if (!utf8_is_valid(word)) { + log_error("Failed to parse %s value %s", field, eq); + return -EINVAL; + } + + offset = word[0] == '-'; + if (!path_is_absolute(word + offset)) { + log_error("Failed to parse %s value %s", field, eq); + return -EINVAL; + } + + path_kill_slashes(word + offset); + + r = sd_bus_message_append_basic(m, 's', word); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); + + } else if (streq(field, "RuntimeDirectory")) { + const char *p; + + r = sd_bus_message_open_container(m, 'v', "as"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_open_container(m, 'a', "s"); + if (r < 0) + return bus_log_create_error(r); + + p = eq; + + for (;;) { + _cleanup_free_ char *word = NULL; + + r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES); + if (r < 0) + return log_error_errno(r, "Failed to parse %s value %s", field, eq); + + if (r == 0) + break; + + r = sd_bus_message_append_basic(m, 's', word); + if (r < 0) + return bus_log_create_error(r); + } + + r = sd_bus_message_close_container(m); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); } else { log_error("Unknown assignment %s.", assignment); return -EINVAL; } +finish: + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_close_container(m); if (r < 0) return bus_log_create_error(r); @@ -1639,8 +1885,7 @@ typedef struct BusWaitForJobs { sd_bus_slot *slot_disconnected; } BusWaitForJobs; -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) { assert(m); @@ -1796,13 +2041,22 @@ static const struct { { "start-limit", "start of the service was attempted too often" } }; -static void log_job_error_with_service_result(const char* service, const char *result) { +static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) { _cleanup_free_ char *service_shell_quoted = NULL; + const char *systemctl = "systemctl", *journalctl = "journalctl"; assert(service); service_shell_quoted = shell_maybe_quote(service); + if (extra_args && extra_args[1]) { + _cleanup_free_ char *t; + + t = strv_join((char**) extra_args, " "); + systemctl = strjoina("systemctl ", t ? : ""); + journalctl = strjoina("journalctl ", t ? : ""); + } + if (!isempty(result)) { unsigned i; @@ -1811,27 +2065,34 @@ static void log_job_error_with_service_result(const char* service, const char *r break; if (i < ELEMENTSOF(explanations)) { - log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n", + log_error("Job for %s failed because %s.\n" + "See \"%s status %s\" and \"%s -xe\" for details.\n", service, explanations[i].explanation, - strna(service_shell_quoted)); - + systemctl, + service_shell_quoted ?: "", + journalctl); goto finish; } } - log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n", + log_error("Job for %s failed.\n" + "See \"%s status %s\" and \"%s -xe\" for details.\n", service, - strna(service_shell_quoted)); + systemctl, + service_shell_quoted ?: "", + journalctl); finish: /* For some results maybe additional explanation is required */ if (streq_ptr(result, "start-limit")) - log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.", - strna(service_shell_quoted)); + log_info("To force a start use \"%1$s reset-failed %2$s\"\n" + "followed by \"%1$s start %2$s\" again.", + systemctl, + service_shell_quoted ?: ""); } -static int check_wait_response(BusWaitForJobs *d, bool quiet) { +static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { int r = 0; assert(d->result); @@ -1844,7 +2105,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) { else if (streq(d->result, "dependency")) log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name)); else if (streq(d->result, "invalid")) - log_error("Job for %s invalid.", strna(d->name)); + log_error("%s is not active, cannot reload.", strna(d->name)); else if (streq(d->result, "assert")) log_error("Assertion failed on job for %s.", strna(d->name)); else if (streq(d->result, "unsupported")) @@ -1858,7 +2119,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) { if (q < 0) log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name); - log_job_error_with_service_result(d->name, result); + log_job_error_with_service_result(d->name, result, extra_args); } else log_error("Job failed. See \"journalctl -xe\" for details."); } @@ -1882,7 +2143,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet) { return r; } -int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) { +int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) { int r = 0; assert(d); @@ -1895,7 +2156,7 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) { return log_error_errno(q, "Failed to wait for response: %m"); if (d->result) { - q = check_wait_response(d, quiet); + q = check_wait_response(d, quiet, extra_args); /* Return the first error as it is most likely to be * meaningful. */ if (q < 0 && r == 0) @@ -1905,7 +2166,6 @@ int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) { } d->name = mfree(d->name); - d->result = mfree(d->result); } @@ -1924,6 +2184,16 @@ int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) { return set_put_strdup(d->jobs, path); } +int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { + int r; + + r = bus_wait_for_jobs_add(d, path); + if (r < 0) + return log_oom(); + + return bus_wait_for_jobs(d, quiet, NULL); +} + int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) { const char *type, *path, *source; int r; @@ -1936,11 +2206,17 @@ int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, Un if (!quiet) { if (streq(type, "symlink")) log_info("Created symlink from %s to %s.", path, source); - else + else if (streq(type, "unlink")) log_info("Removed symlink %s.", path); + else if (streq(type, "masked")) + log_info("Unit %s is masked, ignoring.", path); + else + log_notice("Manager reported unknown change type \"%s\" for %s.", type, path); } - r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source); + r = unit_file_changes_add(changes, n_changes, + unit_file_change_type_from_string(type), + path, source); if (r < 0) return r; } @@ -2115,3 +2391,49 @@ bool is_kdbus_available(void) { return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0; } + +#if 0 /// UNNEEDED by elogind +int bus_property_get_rlimit( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + struct rlimit *rl; + uint64_t u; + rlim_t x; + const char *is_soft; + + assert(bus); + assert(reply); + assert(userdata); + + is_soft = endswith(property, "Soft"); + rl = *(struct rlimit**) userdata; + if (rl) + x = is_soft ? rl->rlim_cur : rl->rlim_max; + else { + struct rlimit buf = {}; + int z; + const char *s; + + s = is_soft ? strndupa(property, is_soft - property) : property; + + z = rlimit_from_string(strstr(s, "Limit")); + assert(z >= 0); + + getrlimit(z, &buf); + x = is_soft ? buf.rlim_cur : buf.rlim_max; + } + + /* rlim_t might have different sizes, let's map + * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on + * all archs */ + u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x; + + return sd_bus_message_append(reply, "t", u); +} +#endif // 0