]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/shared/bus-util.c
util-lib: split out printf() helpers to stdio-util.h
[thirdparty/systemd.git] / src / shared / bus-util.c
index 64a810fc8f9daf35acd04fb5e184f152cdf7bd9c..8f6278191ab09e32e6257f1217320d76133ac143 100644 (file)
 
 #include <sys/socket.h>
 
+#include "sd-bus.h"
 #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-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 "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"
 
 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
         sd_event *e = userdata;
@@ -572,14 +584,14 @@ int bus_check_peercred(sd_bus *c) {
         return 1;
 }
 
-int bus_open_system_systemd(sd_bus **_bus) {
+int bus_connect_system_systemd(sd_bus **_bus) {
         _cleanup_bus_unref_ 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
@@ -614,7 +626,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)
@@ -626,7 +638,7 @@ int bus_open_system_systemd(sd_bus **_bus) {
         return 0;
 }
 
-int bus_open_user_systemd(sd_bus **_bus) {
+int bus_connect_user_systemd(sd_bus **_bus) {
         _cleanup_bus_unref_ sd_bus *bus = NULL;
         _cleanup_free_ char *ee = NULL;
         const char *e;
@@ -656,7 +668,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)
@@ -672,7 +684,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)
@@ -1207,7 +1219,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);
@@ -1242,7 +1254,7 @@ int bus_open_transport(BusTransport transport, const char *host, bool user, sd_b
         return r;
 }
 
-int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
+int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
         int r;
 
         assert(transport >= 0);
@@ -1256,9 +1268,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;
 
@@ -1414,6 +1426,17 @@ 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 r;
+
+                r = sd_bus_message_append(m, "v", "a(sb)", 1,
+                                          eq[0] == '-' ? eq + 1 : eq,
+                                          eq[0] == '-');
+                if (r < 0)
+                        return r;
+                return 0;
         }
 
         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
@@ -1421,9 +1444,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                 return bus_log_create_error(r);
 
         if (STR_IN_SET(field,
-                       "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
+                       "CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
-                       "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit")) {
+                       "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
+                       "PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
+                       "SyslogLevelPrefix")) {
 
                 r = parse_boolean(eq);
                 if (r < 0) {
@@ -1436,18 +1461,48 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
         } else if (streq(field, "MemoryLimit")) {
                 uint64_t bytes;
 
-                r = parse_size(eq, 1024, &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 bytes specification %s", assignment);
+                        log_error("Failed to parse %s value %s.", field, eq);
                         return -EINVAL;
                 }
 
-                r = sd_bus_message_append(m, "v", "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;
@@ -1459,10 +1514,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);
@@ -1574,8 +1653,44 @@ 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")) {
+                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 (!env_assignment_is_valid(word)) {
+                                log_error("Invalid environment assignment: %s", eq);
+                                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;
@@ -1598,6 +1713,79 @@ 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 {
                 log_error("Unknown assignment %s.", assignment);
@@ -2103,3 +2291,42 @@ bool is_kdbus_available(void) {
 
         return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
 }
+
+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;
+
+        assert(bus);
+        assert(reply);
+        assert(userdata);
+
+        rl = *(struct rlimit**) userdata;
+        if (rl)
+                x = rl->rlim_max;
+        else {
+                struct rlimit buf = {};
+                int z;
+
+                z = rlimit_from_string(strstr(property, "Limit"));
+                assert(z >= 0);
+
+                getrlimit(z, &buf);
+                x = 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);
+}