Blob Blame History Raw
From 41bb37959c96b8fddc13b37384b3453393517f4f Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Mon, 13 Jun 2016 19:11:26 +0200
Subject: [PATCH] systemctl: rework "systemctl status" a bit

This reworks "systemctl status" and "systemctl show" a bit. It removes the
definition of the `property_info` structure, because we can simply reuse the
existing UnitStatusInfo type for that.

The "could not be found" message is now printed by show_one() itself (and not
its caller), so that it is shown regardless by who the function is called.
(This makes it necessary to pass the unit name to the function.)

This also adds all properties found to a set, and then checks if any of the
properties passed via "--property=" is mising in it, if so, a proper error is
generated.

Support for checking the PID file of a unit is removed, as this cannot be done
reasonably client side (since the systemd instance we are talking to might sit
on another host)

Replaces: #3411
Fixes: #3425
Also see: #3504

(cherry picked from commit 3dced37b7c2c9a5c733817569d2bbbaa397adaf7)
Related: #1047466
---
 src/systemctl/systemctl.c | 106 +++++++++++++++++++++++++++++-----------------
 1 file changed, 68 insertions(+), 38 deletions(-)

diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index fdda174..93b7a19 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4211,12 +4211,19 @@ static int show_one(
                 const char *verb,
                 sd_bus *bus,
                 const char *path,
+                const char *unit,
                 bool show_properties,
                 bool *new_line,
                 bool *ellipsized) {
 
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+        _cleanup_set_free_ Set *found_properties = NULL;
+        static const struct bus_properties_map property_map[] = {
+                { "LoadState",   "s", NULL, offsetof(UnitStatusInfo, load_state)   },
+                { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
+                {}
+        };
         UnitStatusInfo info = {
                 .memory_current = (uint64_t) -1,
                 .memory_limit = (uint64_t) -1,
@@ -4243,6 +4250,25 @@ static int show_one(
                 return r;
         }
 
+        if (unit) {
+                r = bus_message_map_all_properties(bus, reply, property_map, &info);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
+
+                if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
+                        log_error("Unit %s could not be found.", unit);
+
+                        if (streq(verb, "status"))
+                                return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
+
+                        return -ENOENT;
+                }
+
+                r = sd_bus_message_rewind(reply, true);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
+        }
+
         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
         if (r < 0)
                 return bus_log_parse_error(r);
@@ -4267,9 +4293,17 @@ static int show_one(
                 if (r < 0)
                         return bus_log_parse_error(r);
 
-                if (show_properties)
+                if (show_properties) {
+                        r = set_ensure_allocated(&found_properties, &string_hash_ops);
+                        if (r < 0)
+                                return log_oom();
+
+                        r = set_put(found_properties, name);
+                        if (r < 0 && r != EEXIST)
+                                return log_oom();
+
                         r = print_property(name, reply, contents);
-                else
+                } else
                         r = status_property(name, reply, &info, contents);
                 if (r < 0)
                         return r;
@@ -4291,35 +4325,30 @@ static int show_one(
 
         r = 0;
 
-        if (!show_properties) {
-                if (streq(verb, "help"))
-                        show_unit_help(&info);
+        if (show_properties) {
+                char **pp;
+
+                STRV_FOREACH(pp, arg_properties) {
+                        if (!set_contains(found_properties, *pp)) {
+                                log_warning("Property %s does not exist.", *pp);
+                                r = -ENXIO;
+                        }
+                }
+        } else if (streq(verb, "help"))
+                show_unit_help(&info);
+        else if (streq(verb, "status")) {
+                print_status_info(&info, ellipsized);
+
+                if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
+                        r = EXIT_PROGRAM_NOT_RUNNING;
                 else
-                        print_status_info(&info, ellipsized);
+                        r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
         }
 
         strv_free(info.documentation);
         strv_free(info.dropin_paths);
         strv_free(info.listen);
 
-        if (!streq_ptr(info.active_state, "active") &&
-            !streq_ptr(info.active_state, "reloading") &&
-            streq(verb, "status")) {
-                /* According to LSB: "program not running" */
-                /* 0: program is running or service is OK
-                 * 1: program is dead and /run PID file exists
-                 * 2: program is dead and /run/lock lock file exists
-                 * 3: program is not running
-                 * 4: program or service status is unknown
-                 */
-                if (info.pid_file && access(info.pid_file, F_OK) == 0)
-                        r = EXIT_PROGRAM_DEAD_AND_PID_EXISTS;
-                else if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive"))
-                        r = EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
-                else
-                        r = EXIT_PROGRAM_NOT_RUNNING;
-        }
-
         while ((p = info.exec)) {
                 LIST_REMOVE(exec, info.exec, p);
                 exec_status_info_free(p);
@@ -4394,7 +4423,7 @@ static int show_all(
                 if (!p)
                         return log_oom();
 
-                r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
+                r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
                 if (r < 0)
                         return r;
                 else if (r > 0 && ret == 0)
@@ -4481,9 +4510,8 @@ static int show(sd_bus *bus, char **args) {
                 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
 
         /* If no argument is specified inspect the manager itself */
-
         if (show_properties && strv_length(args) <= 1)
-                return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
+                return show_one(args[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
 
         if (show_status && strv_length(args) <= 1) {
 
@@ -4498,7 +4526,7 @@ static int show(sd_bus *bus, char **args) {
                 char **name;
 
                 STRV_FOREACH(name, args + 1) {
-                        _cleanup_free_ char *unit = NULL;
+                        _cleanup_free_ char *path = NULL, *unit = NULL;
                         uint32_t id;
 
                         if (safe_atou32(*name, &id) < 0) {
@@ -4508,20 +4536,23 @@ static int show(sd_bus *bus, char **args) {
                                 continue;
                         } else if (show_properties) {
                                 /* Interpret as job id */
-                                if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
+                                if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
                                         return log_oom();
 
                         } else {
                                 /* Interpret as PID */
-                                r = get_unit_dbus_path_by_pid(bus, id, &unit);
+                                r = get_unit_dbus_path_by_pid(bus, id, &path);
                                 if (r < 0) {
                                         ret = r;
                                         continue;
                                 }
+
+                                r = unit_name_from_dbus_path(path, &unit);
+                                if (r < 0)
+                                        return log_oom();
                         }
 
-                        r = show_one(args[0], bus, unit, show_properties,
-                                     &new_line, &ellipsized);
+                        r = show_one(args[0], bus, path, unit, show_properties, &new_line, &ellipsized);
                         if (r < 0)
                                 return r;
                         else if (r > 0 && ret == 0)
@@ -4536,17 +4567,16 @@ static int show(sd_bus *bus, char **args) {
                                 log_error_errno(r, "Failed to expand names: %m");
 
                         STRV_FOREACH(name, names) {
-                                _cleanup_free_ char *unit;
+                                _cleanup_free_ char *path;
 
-                                unit = unit_dbus_path_from_name(*name);
-                                if (!unit)
+                                path = unit_dbus_path_from_name(*name);
+                                if (!path)
                                         return log_oom();
 
-                                r = show_one(args[0], bus, unit, show_properties,
-                                             &new_line, &ellipsized);
+                                r = show_one(args[0], bus, path, *name, show_properties, &new_line, &ellipsized);
                                 if (r < 0)
                                         return r;
-                                else if (r > 0 && ret == 0)
+                                if (r > 0 && ret == 0)
                                         ret = r;
                         }
                 }