chiark / gitweb /
Add Listen* to dbus properties
[elogind.git] / src / systemctl / systemctl.c
index 723be76cdbad6a7b168d9a2224d4677a69d5596c..4f4d334794559e4b961588edad938717bd439331 100644 (file)
@@ -136,7 +136,7 @@ static void pager_open_if_enabled(void) {
         if (arg_no_pager)
                 return;
 
-        pager_open();
+        pager_open(false);
 }
 
 static void ask_password_agent_open_if_enabled(void) {
@@ -328,7 +328,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
 
         if (!arg_full) {
                 unsigned basic_len;
-                id_len = MIN(max_id_len, 25);
+                id_len = MIN(max_id_len, 25u);
                 basic_len = 5 + id_len + 5 + active_len + sub_len;
                 if (job_count)
                         basic_len += job_len + 1;
@@ -337,7 +337,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                         extra_len = columns() - basic_len;
                         /* Either UNIT already got 25, or is fully satisfied.
                          * Grant up to 25 to DESC now. */
-                        incr = MIN(extra_len, 25);
+                        incr = MIN(extra_len, 25u);
                         desc_len += incr;
                         extra_len -= incr;
                         /* split the remaining space between UNIT and DESC,
@@ -463,7 +463,7 @@ static int get_unit_list(DBusConnection *bus, DBusMessage **reply,
                 if (*c >= n_units) {
                         struct unit_info *w;
 
-                        n_units = MAX(2 * *c, 16);
+                        n_units = MAX(2 * *c, 16u);
                         w = realloc(*unit_infos, sizeof(struct unit_info) * n_units);
                         if (!w)
                                 return log_oom();
@@ -543,7 +543,7 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
 
         if (!arg_full) {
                 unsigned basic_cols;
-                id_cols = MIN(max_id_len, 25);
+                id_cols = MIN(max_id_len, 25u);
                 basic_cols = 1 + id_cols + state_cols;
                 if (basic_cols < (unsigned) columns())
                         id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
@@ -657,7 +657,7 @@ static int list_unit_files(DBusConnection *bus, char **args) {
                         if (c >= n_units) {
                                 UnitFileList *w;
 
-                                n_units = MAX(2*c, 16);
+                                n_units = MAX(2*c, 16u);
                                 w = realloc(units, sizeof(struct UnitFileList) * n_units);
                                 if (!w)
                                         return log_oom();
@@ -694,7 +694,7 @@ static int list_dependencies_print(const char *name, int level, unsigned int bra
         int i;
         _cleanup_free_ char *n = NULL;
         size_t len = 0;
-        size_t max_len = MAX(columns(),20);
+        size_t max_len = MAX(columns(),20u);
 
         for (i = level - 1; i >= 0; i--) {
                 len += 2;
@@ -1045,7 +1045,7 @@ static bool need_daemon_reload(DBusConnection *bus, const char *unit) {
         if (!n)
                 return log_oom();
 
-        r = bus_method_call_with_reply (
+        r = bus_method_call_with_reply(
                         bus,
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
@@ -1518,53 +1518,39 @@ static int start_unit_one(
         return 0;
 }
 
+static const struct {
+        const char *target;
+        const char *verb;
+        const char *mode;
+} action_table[_ACTION_MAX] = {
+        [ACTION_HALT]         = { SPECIAL_HALT_TARGET,         "halt",         "replace-irreversibly" },
+        [ACTION_POWEROFF]     = { SPECIAL_POWEROFF_TARGET,     "poweroff",     "replace-irreversibly" },
+        [ACTION_REBOOT]       = { SPECIAL_REBOOT_TARGET,       "reboot",       "replace-irreversibly" },
+        [ACTION_KEXEC]        = { SPECIAL_KEXEC_TARGET,        "kexec",        "replace-irreversibly" },
+        [ACTION_RUNLEVEL2]    = { SPECIAL_RUNLEVEL2_TARGET,    NULL,           "isolate" },
+        [ACTION_RUNLEVEL3]    = { SPECIAL_RUNLEVEL3_TARGET,    NULL,           "isolate" },
+        [ACTION_RUNLEVEL4]    = { SPECIAL_RUNLEVEL4_TARGET,    NULL,           "isolate" },
+        [ACTION_RUNLEVEL5]    = { SPECIAL_RUNLEVEL5_TARGET,    NULL,           "isolate" },
+        [ACTION_RESCUE]       = { SPECIAL_RESCUE_TARGET,       "rescue",       "isolate" },
+        [ACTION_EMERGENCY]    = { SPECIAL_EMERGENCY_TARGET,    "emergency",    "isolate" },
+        [ACTION_DEFAULT]      = { SPECIAL_DEFAULT_TARGET,      "default",      "isolate" },
+        [ACTION_EXIT]         = { SPECIAL_EXIT_TARGET,         "exit",         "replace-irreversibly" },
+        [ACTION_SUSPEND]      = { SPECIAL_SUSPEND_TARGET,      "suspend",      "replace-irreversibly" },
+        [ACTION_HIBERNATE]    = { SPECIAL_HIBERNATE_TARGET,    "hibernate",    "replace-irreversibly" },
+        [ACTION_HYBRID_SLEEP] = { SPECIAL_HYBRID_SLEEP_TARGET, "hybrid-sleep", "replace-irreversibly" },
+};
+
 static enum action verb_to_action(const char *verb) {
-        if (streq(verb, "halt"))
-                return ACTION_HALT;
-        else if (streq(verb, "poweroff"))
-                return ACTION_POWEROFF;
-        else if (streq(verb, "reboot"))
-                return ACTION_REBOOT;
-        else if (streq(verb, "kexec"))
-                return ACTION_KEXEC;
-        else if (streq(verb, "rescue"))
-                return ACTION_RESCUE;
-        else if (streq(verb, "emergency"))
-                return ACTION_EMERGENCY;
-        else if (streq(verb, "default"))
-                return ACTION_DEFAULT;
-        else if (streq(verb, "exit"))
-                return ACTION_EXIT;
-        else if (streq(verb, "suspend"))
-                return ACTION_SUSPEND;
-        else if (streq(verb, "hibernate"))
-                return ACTION_HIBERNATE;
-        else if (streq(verb, "hybrid-sleep"))
-                return ACTION_HYBRID_SLEEP;
-        else
-                return ACTION_INVALID;
+        enum action i;
+
+        for (i = ACTION_INVALID; i < _ACTION_MAX; i++)
+                if (action_table[i].verb && streq(verb, action_table[i].verb))
+                        return i;
+        return ACTION_INVALID;
 }
 
 static int start_unit(DBusConnection *bus, char **args) {
 
-        static const char * const table[_ACTION_MAX] = {
-                [ACTION_HALT] = SPECIAL_HALT_TARGET,
-                [ACTION_POWEROFF] = SPECIAL_POWEROFF_TARGET,
-                [ACTION_REBOOT] = SPECIAL_REBOOT_TARGET,
-                [ACTION_KEXEC] = SPECIAL_KEXEC_TARGET,
-                [ACTION_RUNLEVEL2] = SPECIAL_RUNLEVEL2_TARGET,
-                [ACTION_RUNLEVEL3] = SPECIAL_RUNLEVEL3_TARGET,
-                [ACTION_RUNLEVEL4] = SPECIAL_RUNLEVEL4_TARGET,
-                [ACTION_RUNLEVEL5] = SPECIAL_RUNLEVEL5_TARGET,
-                [ACTION_RESCUE] = SPECIAL_RESCUE_TARGET,
-                [ACTION_EMERGENCY] = SPECIAL_EMERGENCY_TARGET,
-                [ACTION_DEFAULT] = SPECIAL_DEFAULT_TARGET,
-                [ACTION_EXIT] = SPECIAL_EXIT_TARGET,
-                [ACTION_SUSPEND] = SPECIAL_SUSPEND_TARGET,
-                [ACTION_HIBERNATE] = SPECIAL_HIBERNATE_TARGET,
-                [ACTION_HYBRID_SLEEP] = SPECIAL_HYBRID_SLEEP_TARGET
-        };
-
         int r, ret = 0;
         const char *method, *mode, *one_name;
         Set _cleanup_set_free_free_ *s = NULL;
@@ -1578,6 +1564,7 @@ static int start_unit(DBusConnection *bus, char **args) {
         ask_password_agent_open_if_enabled();
 
         if (arg_action == ACTION_SYSTEMCTL) {
+                enum action action;
                 method =
                         streq(args[0], "stop") ||
                         streq(args[0], "condstop")              ? "StopUnit" :
@@ -1594,29 +1581,21 @@ static int start_unit(DBusConnection *bus, char **args) {
 
                         streq(args[0], "force-reload")          ? "ReloadOrTryRestartUnit" :
                                                                   "StartUnit";
+                action = verb_to_action(args[0]);
 
-                mode =
-                        (streq(args[0], "isolate") ||
-                         streq(args[0], "rescue")  ||
-                         streq(args[0], "emergency") ||
-                         streq(args[0], "default")) ? "isolate" : arg_job_mode;
+                mode = streq(args[0], "isolate") ? "isolate" :
+                       action_table[action].mode ?: arg_job_mode;
 
-                one_name = table[verb_to_action(args[0])];
+                one_name = action_table[action].target;
 
         } else {
-                assert(arg_action < ELEMENTSOF(table));
-                assert(table[arg_action]);
+                assert(arg_action < ELEMENTSOF(action_table));
+                assert(action_table[arg_action].target);
 
                 method = "StartUnit";
 
-                mode = (arg_action == ACTION_EMERGENCY ||
-                        arg_action == ACTION_RESCUE ||
-                        arg_action == ACTION_RUNLEVEL2 ||
-                        arg_action == ACTION_RUNLEVEL3 ||
-                        arg_action == ACTION_RUNLEVEL4 ||
-                        arg_action == ACTION_RUNLEVEL5) ? "isolate" : "replace";
-
-                one_name = table[arg_action];
+                mode = action_table[arg_action].mode;
+                one_name = action_table[arg_action].target;
         }
 
         if (!arg_no_block) {
@@ -1839,12 +1818,7 @@ static int check_inhibitors(DBusConnection *bus, enum action a) {
                 return 0;
 
         log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.",
-                  a == ACTION_HALT ? "halt" :
-                  a == ACTION_POWEROFF ? "poweroff" :
-                  a == ACTION_REBOOT ? "reboot" :
-                  a == ACTION_KEXEC ? "kexec" :
-                  a == ACTION_SUSPEND ? "suspend" :
-                  a == ACTION_HIBERNATE ? "hibernate" : "hybrid-sleep");
+                  action_table[a].verb);
 
         return -EPERM;
 #else
@@ -1989,53 +1963,41 @@ static int kill_unit(DBusConnection *bus, char **args) {
 }
 
 static int set_cgroup(DBusConnection *bus, char **args) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        DBusError error;
-        const char *method;
-        DBusMessageIter iter;
-        int r;
         _cleanup_free_ char *n = NULL;
-        const char *runtime;
+        const char *method, *runtime;
+        char **argument;
+        int r;
 
         assert(bus);
         assert(args);
 
-        dbus_error_init(&error);
-
         method =
-                streq(args[0], "set-cgroup")  ? "SetUnitControlGroups" :
-                streq(args[0], "unset-group") ? "UnsetUnitControlGroups"
-                                              : "UnsetUnitControlGroupAttributes";
+                streq(args[0], "set-cgroup")   ? "SetUnitControlGroup" :
+                streq(args[0], "unset-cgroup") ? "UnsetUnitControlGroup"
+                                               : "UnsetUnitControlGroupAttribute";
+
+        runtime = arg_runtime ? "runtime" : "persistent";
 
         n = unit_name_mangle(args[1]);
         if (!n)
                 return log_oom();
 
-        m = dbus_message_new_method_call(
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        method);
-        if (!m)
-                return log_oom();
-
-        dbus_message_iter_init_append(m, &iter);
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
-                return log_oom();
-
-        r = bus_append_strv_iter(&iter, args + 2);
-        if (r < 0)
-                return log_oom();
+        STRV_FOREACH(argument, args + 2) {
 
-        runtime = arg_runtime ? "runtime" : "persistent";
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
-                return log_oom();
-
-        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
-        if (!reply) {
-                log_error("Failed to issue method call: %s", bus_error_message(&error));
-                dbus_error_free(&error);
-                return -EIO;
+                r = bus_method_call_with_reply(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                method,
+                                NULL,
+                                NULL,
+                                DBUS_TYPE_STRING, &n,
+                                DBUS_TYPE_STRING, argument,
+                                DBUS_TYPE_STRING, &runtime,
+                                DBUS_TYPE_INVALID);
+                if (r < 0)
+                        return r;
         }
 
         return 0;
@@ -2044,20 +2006,17 @@ static int set_cgroup(DBusConnection *bus, char **args) {
 static int set_cgroup_attr(DBusConnection *bus, char **args) {
         _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
         DBusError error;
-        DBusMessageIter iter, sub, sub2;
-        char **x, **y;
+        DBusMessageIter iter;
         _cleanup_free_ char *n = NULL;
         const char *runtime;
+        int r;
 
         assert(bus);
         assert(args);
 
         dbus_error_init(&error);
 
-        if (strv_length(args) % 2 != 0) {
-                log_error("Expecting an uneven number of arguments!");
-                return -EINVAL;
-        }
+        runtime = arg_runtime ? "runtime" : "persistent";
 
         n = unit_name_mangle(args[1]);
         if (!n)
@@ -2067,26 +2026,20 @@ static int set_cgroup_attr(DBusConnection *bus, char **args) {
                         "org.freedesktop.systemd1",
                         "/org/freedesktop/systemd1",
                         "org.freedesktop.systemd1.Manager",
-                        "SetUnitControlGroupAttributes");
+                        "SetUnitControlGroupAttribute");
         if (!m)
                 return log_oom();
 
         dbus_message_iter_init_append(m, &iter);
         if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n) ||
-            !dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ss)", &sub))
+            !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &args[2]))
                 return log_oom();
 
-        STRV_FOREACH_PAIR(x, y, args + 2) {
-                if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, x) ||
-                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, y) ||
-                    !dbus_message_iter_close_container(&sub, &sub2))
-                        return log_oom();
-        }
+        r = bus_append_strv_iter(&iter, args + 3);
+        if (r < 0)
+                return log_oom();
 
-        runtime = arg_runtime ? "runtime" : "persistent";
-        if (!dbus_message_iter_close_container(&iter, &sub) ||
-            !dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
+        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &runtime))
                 return log_oom();
 
         reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
@@ -2100,58 +2053,54 @@ static int set_cgroup_attr(DBusConnection *bus, char **args) {
 }
 
 static int get_cgroup_attr(DBusConnection *bus, char **args) {
-        _cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
-        DBusError error;
-        DBusMessageIter iter;
-        int r;
+        _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         _cleanup_free_ char *n = NULL;
-        _cleanup_strv_free_ char **list = NULL;
-        char **a;
+        char **argument;
+        int r;
 
         assert(bus);
         assert(args);
 
-        dbus_error_init(&error);
-
         n = unit_name_mangle(args[1]);
         if (!n)
                 return log_oom();
 
-        m = dbus_message_new_method_call(
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "GetUnitControlGroupAttributes");
-        if (!m)
-                return log_oom();
-
-        dbus_message_iter_init_append(m, &iter);
-        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &n))
-                return log_oom();
+        STRV_FOREACH(argument, args + 2) {
+                _cleanup_strv_free_ char **list = NULL;
+                DBusMessageIter iter;
+                char **a;
 
-        r = bus_append_strv_iter(&iter, args + 2);
-        if (r < 0)
-                return log_oom();
+                r = bus_method_call_with_reply(
+                                bus,
+                                "org.freedesktop.systemd1",
+                                "/org/freedesktop/systemd1",
+                                "org.freedesktop.systemd1.Manager",
+                                "GetUnitControlGroupAttribute",
+                                &reply,
+                                NULL,
+                                DBUS_TYPE_STRING, &n,
+                                DBUS_TYPE_STRING, argument,
+                                DBUS_TYPE_INVALID);
+                if (r < 0)
+                        return r;
 
-        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
-        if (!reply) {
-                log_error("Failed to issue method call: %s", bus_error_message(&error));
-                dbus_error_free(&error);
-                return -EIO;
-        }
+                if (!dbus_message_iter_init(reply, &iter)) {
+                        log_error("Failed to initialize iterator.");
+                        return -EIO;
+                }
 
-        dbus_message_iter_init(reply, &iter);
-        r = bus_parse_strv_iter(&iter, &list);
-        if (r < 0) {
-                log_error("Failed to parse value list.");
-                return r;
-        }
+                r = bus_parse_strv_iter(&iter, &list);
+                if (r < 0) {
+                        log_error("Failed to parse value list.");
+                        return r;
+                }
 
-        STRV_FOREACH(a, list) {
-                if (endswith(*a, "\n"))
-                        fputs(*a, stdout);
-                else
-                        puts(*a);
+                STRV_FOREACH(a, list) {
+                        if (endswith(*a, "\n"))
+                                fputs(*a, stdout);
+                        else
+                                puts(*a);
+                }
         }
 
         return 0;
@@ -2306,6 +2255,8 @@ typedef struct UnitStatusInfo {
         unsigned n_connections;
         bool accept;
 
+        char **listen;
+
         /* Device */
         const char *sysfs_path;
 
@@ -2437,6 +2388,19 @@ static void print_status_info(UnitStatusInfo *i) {
                 }
         }
 
+        if (!strv_isempty(i->listen)) {
+                char **t;
+                bool first = true;
+
+                STRV_FOREACH(t, i->listen) {
+                        if (first) {
+                                printf("\t  Listen: %s\n", *t);
+                                first = false;
+                        } else
+                                printf("\t          %s\n", *t);
+                }
+        }
+
         if (i->accept)
                 printf("\tAccepted: %u; Connected: %u\n", i->n_accepted, i->n_connections);
 
@@ -2560,23 +2524,15 @@ static void print_status_info(UnitStatusInfo *i) {
 
         if (i->id && arg_transport != TRANSPORT_SSH) {
                 printf("\n");
-                if(arg_scope == UNIT_FILE_SYSTEM)
-                        show_journal_by_unit(stdout,
-                                             i->id,
-                                             arg_output,
-                                             0,
-                                             i->inactive_exit_timestamp_monotonic,
-                                             arg_lines,
-                                             flags);
-                else
-                        show_journal_by_user_unit(stdout,
-                                                  i->id,
-                                                  arg_output,
-                                                  0,
-                                                  i->inactive_exit_timestamp_monotonic,
-                                                  arg_lines,
-                                                  getuid(),
-                                                  flags);
+                show_journal_by_unit(stdout,
+                                     i->id,
+                                     arg_output,
+                                     0,
+                                     i->inactive_exit_timestamp_monotonic,
+                                     arg_lines,
+                                     getuid(),
+                                     flags,
+                                     arg_scope == UNIT_FILE_SYSTEM);
         }
 
         if (i->need_daemon_reload)
@@ -2795,6 +2751,37 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
 
                                 dbus_message_iter_next(&sub);
                         }
+
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
+                        DBusMessageIter sub, sub2;
+
+                        dbus_message_iter_recurse(iter, &sub);
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *type, *path;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+
+                                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0) {
+                                        char * buf, **l;
+                                        if (asprintf(&buf, "%s: %s", type, path) < 0)
+                                                return -ENOMEM;
+
+                                        l = strv_append(i->listen, buf);
+                                        free(buf);
+
+                                        if (!l)
+                                                return -ENOMEM;
+
+                                        strv_free(i->listen);
+                                        i->listen = l;
+                                }
+
+                                dbus_message_iter_next(&sub);
+                        }
+
+                        return 0;
+
                 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
                            streq(name, "Documentation")) {
 
@@ -2925,6 +2912,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                         DBusMessageIter sub, sub2;
 
                         dbus_message_iter_recurse(iter, &sub);
+
                         while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
                                 const char *type, *path;
 
@@ -2939,6 +2927,24 @@ static int print_property(const char *name, DBusMessageIter *iter) {
 
                         return 0;
 
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
+                        DBusMessageIter sub, sub2;
+
+                        dbus_message_iter_recurse(iter, &sub);
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *type, *path;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+
+                                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
+                                        printf("Listen%s=%s\n", type, path);
+
+                                dbus_message_iter_next(&sub);
+                        }
+
+                        return 0;
+
                 } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
                         DBusMessageIter sub, sub2;
 
@@ -3039,7 +3045,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
 }
 
 static int show_one(const char *verb, DBusConnection *bus, const char *path, bool show_properties, bool *new_line) {
-        _cleanup_free_ DBusMessage *reply = NULL;
+        DBusMessage _cleanup_free_ *reply = NULL;
         const char *interface = "";
         int r;
         DBusMessageIter iter, sub, sub2, sub3;
@@ -3114,6 +3120,7 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
         }
 
         strv_free(info.documentation);
+        strv_free(info.listen);
 
         if (!streq_ptr(info.active_state, "active") &&
             !streq_ptr(info.active_state, "reloading") &&
@@ -4011,16 +4018,15 @@ static int enable_unit(DBusConnection *bus, char **args) {
         }
 
         if (carries_install_info == 0)
-                log_warning(
-"The unit files have no [Install] section. They are not meant to be enabled\n"
-"using systemctl.\n"
-"Possible reasons for having this kind of units are:\n"
-"1) A unit may be statically enabled by being symlinked from another unit's\n"
-"   .wants/ or .requires/ directory.\n"
-"2) A unit's purpose may be to act as a helper for some other unit which has\n"
-"   a requirement dependency on it.\n"
-"3) A unit may be started when needed via activation (socket, path, timer,\n"
-"   D-Bus, udev, scripted systemctl call, ...).\n");
+                log_warning("The unit files have no [Install] section. They are not meant to be enabled\n"
+                            "using systemctl.\n"
+                            "Possible reasons for having this kind of units are:\n"
+                            "1) A unit may be statically enabled by being symlinked from another unit's\n"
+                            "   .wants/ or .requires/ directory.\n"
+                            "2) A unit's purpose may be to act as a helper for some other unit which has\n"
+                            "   a requirement dependency on it.\n"
+                            "3) A unit may be started when needed via activation (socket, path, timer,\n"
+                            "   D-Bus, udev, scripted systemctl call, ...).\n");
 
 finish:
         unit_file_changes_free(changes, n_changes);
@@ -4034,6 +4040,7 @@ static int unit_is_enabled(DBusConnection *bus, char **args) {
         DBusMessage _cleanup_dbus_message_unref_ *reply = NULL;
         bool enabled;
         char **name;
+        char *n;
 
         dbus_error_init(&error);
 
@@ -4048,7 +4055,14 @@ static int unit_is_enabled(DBusConnection *bus, char **args) {
                 STRV_FOREACH(name, args+1) {
                         UnitFileState state;
 
-                        state = unit_file_get_state(arg_scope, arg_root, *name);
+                        n = unit_name_mangle(*name);
+                        if (!n)
+                                return log_oom();
+
+                        state = unit_file_get_state(arg_scope, arg_root, n);
+
+                        free(n);
+
                         if (state < 0)
                                 return state;
 
@@ -4065,6 +4079,10 @@ static int unit_is_enabled(DBusConnection *bus, char **args) {
                 STRV_FOREACH(name, args+1) {
                         const char *s;
 
+                        n = unit_name_mangle(*name);
+                        if (!n)
+                                return log_oom();
+
                         r = bus_method_call_with_reply (
                                         bus,
                                         "org.freedesktop.systemd1",
@@ -4073,8 +4091,11 @@ static int unit_is_enabled(DBusConnection *bus, char **args) {
                                         "GetUnitFileState",
                                         &reply,
                                         NULL,
-                                        DBUS_TYPE_STRING, name,
+                                        DBUS_TYPE_STRING, &n,
                                         DBUS_TYPE_INVALID);
+
+                        free(n);
+
                         if (r)
                                 return r;
 
@@ -4288,16 +4309,21 @@ static int runlevel_help(void) {
 
 static int help_types(void) {
         int i;
+        const char *t;
 
         puts("Available unit types:");
-        for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
-                if (unit_type_table[i])
-                        puts(unit_type_table[i]);
+        for(i = 0; i < _UNIT_TYPE_MAX; i++) {
+                t = unit_type_to_string(i);
+                if (t)
+                        puts(t);
+        }
 
         puts("\nAvailable unit load states: ");
-        for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
-                if (unit_type_table[i])
-                        puts(unit_load_state_table[i]);
+        for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
+                t = unit_load_state_to_string(i);
+                if (t)
+                        puts(t);
+        }
 
         return 0;
 }
@@ -4674,11 +4700,11 @@ static int parse_time_spec(const char *t, usec_t *_u) {
 
                 errno = 0;
                 hour = strtol(t, &e, 10);
-                if (errno != 0 || *e != ':' || hour < 0 || hour > 23)
+                if (errno > 0 || *e != ':' || hour < 0 || hour > 23)
                         return -EINVAL;
 
                 minute = strtol(e+1, &e, 10);
-                if (errno != 0 || *e != 0 || minute < 0 || minute > 59)
+                if (errno > 0 || *e != 0 || minute < 0 || minute > 59)
                         return -EINVAL;
 
                 n = now(CLOCK_REALTIME);
@@ -4963,7 +4989,7 @@ static int parse_argv(int argc, char *argv[]) {
                                  * request to it. For now we simply
                                  * guess that it is Upstart. */
 
-                                execv("/lib/upstart/telinit", argv);
+                                execv(TELINIT, argv);
 
                                 log_error("Couldn't find an alternative telinit implementation to spawn.");
                                 return -EIO;
@@ -5086,21 +5112,22 @@ finish:
 }
 
 static int talk_initctl(void) {
-        struct init_request request;
-        int r, fd;
+        struct init_request request = {0};
+        int r;
+        int _cleanup_close_ fd = -1;
         char rl;
 
-        if (!(rl = action_to_runlevel()))
+        rl = action_to_runlevel();
+        if (!rl)
                 return 0;
 
-        zero(request);
         request.magic = INIT_MAGIC;
         request.sleeptime = 0;
         request.cmd = INIT_CMD_RUNLVL;
         request.runlevel = rl;
 
-        if ((fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY)) < 0) {
-
+        fd = open(INIT_FIFO, O_WRONLY|O_NDELAY|O_CLOEXEC|O_NOCTTY);
+        if (fd < 0) {
                 if (errno == ENOENT)
                         return 0;
 
@@ -5110,9 +5137,7 @@ static int talk_initctl(void) {
 
         errno = 0;
         r = loop_write(fd, &request, sizeof(request), false) != sizeof(request);
-        close_nointr_nofail(fd);
-
-        if (r < 0) {
+        if (r) {
                 log_error("Failed to write to "INIT_FIFO": %m");
                 return errno ? -errno : -EIO;
         }
@@ -5150,11 +5175,11 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "condreload",            MORE,  2, start_unit        }, /* For compatibility with ALTLinux */
                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
                 { "isolate",               EQUAL, 2, start_unit        },
-                { "set-cgroup",            MORE,  2, set_cgroup        },
-                { "unset-cgroup",          MORE,  2, set_cgroup        },
-                { "get-cgroup-attr",       MORE,  2, get_cgroup_attr   },
-                { "set-cgroup-attr",       MORE,  2, set_cgroup_attr   },
-                { "unset-cgroup-attr",     MORE,  2, set_cgroup        },
+                { "set-cgroup",            MORE,  3, set_cgroup        },
+                { "unset-cgroup",          MORE,  3, set_cgroup        },
+                { "get-cgroup-attr",       MORE,  3, get_cgroup_attr   },
+                { "set-cgroup-attr",       MORE,  4, set_cgroup_attr   },
+                { "unset-cgroup-attr",     MORE,  3, set_cgroup        },
                 { "kill",                  MORE,  2, kill_unit         },
                 { "is-active",             MORE,  2, check_unit_active },
                 { "check",                 MORE,  2, check_unit_active },