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=c12795d1f397402611d3f21e66326140db3dc992;hp=cd05a82d345cc5be54b63fa976484bdf0e2b075d;hb=f959e21a0603238f2e4566cf92266f50b59c7476;hpb=d2338db3145922b1dfcb3b458e5bce2568a9347a diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index cd05a82d3..c12795d1f 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -19,29 +19,42 @@ along with systemd; If not, see . ***/ -// #include +#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 "sd-daemon.h" +#include "sd-event.h" -// #include "sd-bus.h" -// #include "bus-error.h" -// #include "bus-label.h" +#include "alloc-util.h" +#include "bus-error.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 "fd-util.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 "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; @@ -551,8 +564,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; @@ -1146,8 +1158,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, @@ -1229,8 +1240,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s 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,8 +1264,7 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s return r; } -/// UNNEEDED by elogind -#if 0 +#if 0 /// UNNEEDED by elogind int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) { int r; @@ -1356,8 +1365,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"); } @@ -1431,6 +1439,37 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen return bus_log_create_error(r); return 0; + + } else if (streq(field, "EnvironmentFile")) { + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "EnvironmentFiles"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "v", "a(sb)", 1, + eq[0] == '-' ? eq + 1 : eq, + eq[0] == '-'); + if (r < 0) + return bus_log_create_error(r); + + return 0; + + } else if (streq(field, "RandomizedDelaySec")) { + usec_t t; + + r = parse_sec(eq, &t); + if (r < 0) + return log_error_errno(r, "Failed to parse RandomizedDelaySec= parameter: %s", eq); + + r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "RandomizedDelayUSec"); + if (r < 0) + return bus_log_create_error(r); + + r = sd_bus_message_append(m, "v", "t", t); + if (r < 0) + return bus_log_create_error(r); + + return 0; } r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field); @@ -1441,13 +1480,12 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting", "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies", "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit", - "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges")) { + "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); @@ -1508,10 +1546,33 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath", "StandardInput", "StandardOutput", "StandardError", "Description", "Slice", "Type", "WorkingDirectory", - "RootDirectory")) + "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); @@ -1622,9 +1683,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; @@ -1647,6 +1751,113 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen } r = sd_bus_message_append(m, "v", "t", u); + } else if (streq(field, "TimerSlackNSec")) { + nsec_t n; + + 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", 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); @@ -1671,8 +1882,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); @@ -1828,13 +2038,21 @@ 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) { - _cleanup_free_ char *service_shell_quoted = NULL; +static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) { + _cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL; assert(service); service_shell_quoted = shell_maybe_quote(service); + systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL); + if (!systemctl_extra_args) { + log_oom(); + return; + } + + systemctl_extra_args = strstrip(systemctl_extra_args); + if (!isempty(result)) { unsigned i; @@ -1843,27 +2061,30 @@ 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. See \"%s status %s\" and \"journalctl -xe\" for details.\n", service, explanations[i].explanation, + systemctl_extra_args, strna(service_shell_quoted)); goto finish; } } - log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n", + log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n", service, + systemctl_extra_args, strna(service_shell_quoted)); 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.", + log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.", + systemctl_extra_args, strna(service_shell_quoted)); } -static int check_wait_response(BusWaitForJobs *d, bool quiet) { +static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) { int r = 0; assert(d->result); @@ -1876,7 +2097,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")) @@ -1890,7 +2111,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."); } @@ -1914,7 +2135,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 *extra_args) { int r = 0; assert(d); @@ -1927,7 +2148,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) @@ -1962,7 +2183,7 @@ int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) { if (r < 0) return log_oom(); - return bus_wait_for_jobs(d, quiet); + 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) { @@ -2156,3 +2377,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