chiark / gitweb /
systemctl: fix exit statuses from is-active/is-failed
[elogind.git] / src / systemctl / systemctl.c
index 01a4489f4d09e4ed82feaa761965827ecfd42d71..ef0cbc5bf4ee980223d523efabf143c1443a17dd 100644 (file)
@@ -58,7 +58,6 @@
 #include "path-lookup.h"
 #include "conf-parser.h"
 #include "exit-status.h"
-#include "bus-errors.h"
 #include "build.h"
 #include "unit-name.h"
 #include "pager.h"
@@ -68,6 +67,7 @@
 #include "logs-show.h"
 #include "socket-util.h"
 #include "fileio.h"
+#include "env-util.h"
 #include "bus-util.h"
 #include "bus-message.h"
 #include "bus-error.h"
@@ -1327,7 +1327,7 @@ static int list_dependencies_one(
                 char ***units,
                 unsigned int branches) {
 
-        _cleanup_strv_free_ char **deps = NULL, **u;
+        _cleanup_strv_free_ char **deps = NULL;
         char **c;
         int r = 0;
 
@@ -1335,8 +1335,8 @@ static int list_dependencies_one(
         assert(name);
         assert(units);
 
-        u = strv_append(*units, name);
-        if (!u)
+        r = strv_extend(units, name);
+        if (r < 0)
                 return log_oom();
 
         r = list_dependencies_get_dependencies(bus, name, &deps);
@@ -1348,7 +1348,7 @@ static int list_dependencies_one(
         STRV_FOREACH(c, deps) {
                 int state;
 
-                if (strv_contains(u, *c)) {
+                if (strv_contains(*units, *c)) {
                         if (!arg_plain) {
                                 r = list_dependencies_print("...", level + 1, (branches << 1) | (c[1] == NULL ? 0 : 1), 1);
                                 if (r < 0)
@@ -1368,17 +1368,14 @@ static int list_dependencies_one(
                         return r;
 
                 if (arg_all || unit_name_to_type(*c) == UNIT_TARGET) {
-                       r = list_dependencies_one(bus, *c, level + 1, &u, (branches << 1) | (c[1] == NULL ? 0 : 1));
+                       r = list_dependencies_one(bus, *c, level + 1, units, (branches << 1) | (c[1] == NULL ? 0 : 1));
                        if (r < 0)
                                return r;
                 }
         }
 
-        if (arg_plain) {
-                strv_free(*units);
-                *units = u;
-                u = NULL;
-        }
+        if (!arg_plain)
+                strv_remove(*units, name);
 
         return 0;
 }
@@ -2514,14 +2511,16 @@ static int start_special(sd_bus *bus, char **args) {
 static int check_unit_generic(sd_bus *bus, int code, const char *good_states, char **args) {
         _cleanup_strv_free_ char **names = NULL;
         char **name;
-        int r = code;
+        int r;
 
         assert(bus);
         assert(args);
 
         r = expand_names(bus, args, NULL, &names);
-        if (r < 0)
+        if (r < 0) {
                 log_error("Failed to expand names: %s", strerror(-r));
+                return r;
+        }
 
         STRV_FOREACH(name, names) {
                 int state;
@@ -2529,8 +2528,8 @@ static int check_unit_generic(sd_bus *bus, int code, const char *good_states, ch
                 state = check_one_unit(bus, *name, good_states, arg_quiet);
                 if (state < 0)
                         return state;
-                if (state > 0)
-                        r = 0;
+                if (state == 0)
+                        r = code;
         }
 
         return r;
@@ -3407,6 +3406,48 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
                         if (arg_all || !isempty(a) || !isempty(b))
                                 printf("%s=%s \"%s\"\n", name, strempty(a), strempty(b));
 
+                        return 0;
+                } else if (streq_ptr(name, "SystemCallFilter")) {
+                        _cleanup_strv_free_ char **l = NULL;
+                        int whitelist;
+
+                        r = sd_bus_message_enter_container(m, 'r', "bas");
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_read(m, "b", &whitelist);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_read_strv(m, &l);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        r = sd_bus_message_exit_container(m);
+                        if (r < 0)
+                                return bus_log_parse_error(r);
+
+                        if (arg_all || whitelist || !strv_isempty(l)) {
+                                bool first = true;
+                                char **i;
+
+                                fputs(name, stdout);
+                                fputc('=', stdout);
+
+                                if (!whitelist)
+                                        fputc('~', stdout);
+
+                                STRV_FOREACH(i, l) {
+                                        if (first)
+                                                first = false;
+                                        else
+                                                fputc(' ', stdout);
+
+                                        fputs(*i, stdout);
+                                }
+                                fputc('\n', stdout);
+                        }
+
                         return 0;
                 }
 
@@ -4470,6 +4511,69 @@ static int set_environment(sd_bus *bus, char **args) {
         return 0;
 }
 
+static int import_environment(sd_bus *bus, char **args) {
+        _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
+        int r;
+
+        assert(bus);
+        assert(args);
+
+        r = sd_bus_message_new_method_call(
+                        bus,
+                        "org.freedesktop.systemd1",
+                        "/org/freedesktop/systemd1",
+                        "org.freedesktop.systemd1.Manager",
+                        "SetEnvironment",
+                        &m);
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        if (strv_isempty(args + 1))
+                r = sd_bus_message_append_strv(m, environ);
+        else {
+                char **a, **b;
+
+                r = sd_bus_message_open_container(m, 'a', "s");
+                if (r < 0)
+                        return bus_log_create_error(r);
+
+                STRV_FOREACH(a, args + 1) {
+
+                        if (!env_name_is_valid(*a)) {
+                                log_error("Not a valid environment variable name: %s", *a);
+                                return -EINVAL;
+                        }
+
+                        STRV_FOREACH(b, environ) {
+                                const char *eq;
+
+                                eq = startswith(*b, *a);
+                                if (eq && *eq == '=') {
+
+                                        r = sd_bus_message_append(m, "s", *b);
+                                        if (r < 0)
+                                                return bus_log_create_error(r);
+
+                                        break;
+                                }
+                        }
+                }
+
+                r = sd_bus_message_close_container(m);
+        }
+        if (r < 0)
+                return bus_log_create_error(r);
+
+        r = sd_bus_call(bus, m, 0, &error, NULL);
+        if (r < 0) {
+                log_error("Failed to import environment: %s", bus_error_message(&error, r));
+                return r;
+        }
+
+        return 0;
+}
+
 static int enable_sysv_units(const char *verb, char **args) {
         int r = 0;
 
@@ -4679,6 +4783,11 @@ static int enable_unit(sd_bus *bus, char **args) {
         if (r < 0)
                 return r;
 
+        /* If the operation was fully executed by the SysV compat,
+         * let's finish early */
+        if (strv_isempty(names))
+                return 0;
+
         if (!bus || avoid_bus()) {
                 if (streq(verb, "enable")) {
                         r = unit_file_enable(arg_scope, arg_runtime, arg_root, names, arg_force, &changes, &n_changes);
@@ -4974,7 +5083,8 @@ static int systemctl_help(void) {
                "Environment Commands:\n"
                "  show-environment                Dump environment\n"
                "  set-environment NAME=VALUE...   Set one or more environment variables\n"
-               "  unset-environment NAME...       Unset one or more environment variables\n\n"
+               "  unset-environment NAME...       Unset one or more environment variables\n"
+               "  import-environment NAME...      Import all, one or more environment variables\n\n"
                "Manager Lifecycle Commands:\n"
                "  daemon-reload                   Reload systemd manager configuration\n"
                "  daemon-reexec                   Reexecute systemd manager\n\n"
@@ -5940,6 +6050,7 @@ static int systemctl_main(sd_bus *bus, int argc, char *argv[], int bus_error) {
                 { "show-environment",      EQUAL, 1, show_environment  },
                 { "set-environment",       MORE,  2, set_environment   },
                 { "unset-environment",     MORE,  2, set_environment   },
+                { "import-environment",    MORE,  1, import_environment},
                 { "halt",                  EQUAL, 1, start_special,    FORCE },
                 { "poweroff",              EQUAL, 1, start_special,    FORCE },
                 { "reboot",                EQUAL, 1, start_special,    FORCE },