803fb7
From 41bb37959c96b8fddc13b37384b3453393517f4f Mon Sep 17 00:00:00 2001
803fb7
From: Lennart Poettering <lennart@poettering.net>
803fb7
Date: Mon, 13 Jun 2016 19:11:26 +0200
803fb7
Subject: [PATCH] systemctl: rework "systemctl status" a bit
803fb7
803fb7
This reworks "systemctl status" and "systemctl show" a bit. It removes the
803fb7
definition of the `property_info` structure, because we can simply reuse the
803fb7
existing UnitStatusInfo type for that.
803fb7
803fb7
The "could not be found" message is now printed by show_one() itself (and not
803fb7
its caller), so that it is shown regardless by who the function is called.
803fb7
(This makes it necessary to pass the unit name to the function.)
803fb7
803fb7
This also adds all properties found to a set, and then checks if any of the
803fb7
properties passed via "--property=" is mising in it, if so, a proper error is
803fb7
generated.
803fb7
803fb7
Support for checking the PID file of a unit is removed, as this cannot be done
803fb7
reasonably client side (since the systemd instance we are talking to might sit
803fb7
on another host)
803fb7
803fb7
Replaces: #3411
803fb7
Fixes: #3425
803fb7
Also see: #3504
803fb7
803fb7
(cherry picked from commit 3dced37b7c2c9a5c733817569d2bbbaa397adaf7)
803fb7
Related: #1047466
803fb7
---
de8967
 src/systemctl/systemctl.c | 106 ++++++++++++++++++++++++--------------
803fb7
 1 file changed, 68 insertions(+), 38 deletions(-)
803fb7
803fb7
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
803fb7
index fdda174ae..93b7a193b 100644
803fb7
--- a/src/systemctl/systemctl.c
803fb7
+++ b/src/systemctl/systemctl.c
803fb7
@@ -4211,12 +4211,19 @@ static int show_one(
803fb7
                 const char *verb,
803fb7
                 sd_bus *bus,
803fb7
                 const char *path,
803fb7
+                const char *unit,
803fb7
                 bool show_properties,
803fb7
                 bool *new_line,
803fb7
                 bool *ellipsized) {
803fb7
 
803fb7
         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
803fb7
         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
803fb7
+        _cleanup_set_free_ Set *found_properties = NULL;
803fb7
+        static const struct bus_properties_map property_map[] = {
803fb7
+                { "LoadState",   "s", NULL, offsetof(UnitStatusInfo, load_state)   },
803fb7
+                { "ActiveState", "s", NULL, offsetof(UnitStatusInfo, active_state) },
803fb7
+                {}
803fb7
+        };
803fb7
         UnitStatusInfo info = {
803fb7
                 .memory_current = (uint64_t) -1,
803fb7
                 .memory_limit = (uint64_t) -1,
803fb7
@@ -4243,6 +4250,25 @@ static int show_one(
803fb7
                 return r;
803fb7
         }
803fb7
 
803fb7
+        if (unit) {
803fb7
+                r = bus_message_map_all_properties(bus, reply, property_map, &info;;
803fb7
+                if (r < 0)
803fb7
+                        return log_error_errno(r, "Failed to map properties: %s", bus_error_message(&error, r));
803fb7
+
803fb7
+                if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive")) {
803fb7
+                        log_error("Unit %s could not be found.", unit);
803fb7
+
803fb7
+                        if (streq(verb, "status"))
803fb7
+                                return EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
803fb7
+
803fb7
+                        return -ENOENT;
803fb7
+                }
803fb7
+
803fb7
+                r = sd_bus_message_rewind(reply, true);
803fb7
+                if (r < 0)
803fb7
+                        return log_error_errno(r, "Failed to rewind: %s", bus_error_message(&error, r));
803fb7
+        }
803fb7
+
803fb7
         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
803fb7
         if (r < 0)
803fb7
                 return bus_log_parse_error(r);
803fb7
@@ -4267,9 +4293,17 @@ static int show_one(
803fb7
                 if (r < 0)
803fb7
                         return bus_log_parse_error(r);
803fb7
 
803fb7
-                if (show_properties)
803fb7
+                if (show_properties) {
803fb7
+                        r = set_ensure_allocated(&found_properties, &string_hash_ops);
803fb7
+                        if (r < 0)
803fb7
+                                return log_oom();
803fb7
+
803fb7
+                        r = set_put(found_properties, name);
803fb7
+                        if (r < 0 && r != EEXIST)
803fb7
+                                return log_oom();
803fb7
+
803fb7
                         r = print_property(name, reply, contents);
803fb7
-                else
803fb7
+                } else
803fb7
                         r = status_property(name, reply, &info, contents);
803fb7
                 if (r < 0)
803fb7
                         return r;
803fb7
@@ -4291,35 +4325,30 @@ static int show_one(
803fb7
 
803fb7
         r = 0;
803fb7
 
803fb7
-        if (!show_properties) {
803fb7
-                if (streq(verb, "help"))
803fb7
-                        show_unit_help(&info;;
803fb7
+        if (show_properties) {
803fb7
+                char **pp;
803fb7
+
803fb7
+                STRV_FOREACH(pp, arg_properties) {
803fb7
+                        if (!set_contains(found_properties, *pp)) {
803fb7
+                                log_warning("Property %s does not exist.", *pp);
803fb7
+                                r = -ENXIO;
803fb7
+                        }
803fb7
+                }
803fb7
+        } else if (streq(verb, "help"))
803fb7
+                show_unit_help(&info;;
803fb7
+        else if (streq(verb, "status")) {
803fb7
+                print_status_info(&info, ellipsized);
803fb7
+
803fb7
+                if (info.active_state && STR_IN_SET(info.active_state, "inactive", "failed"))
803fb7
+                        r = EXIT_PROGRAM_NOT_RUNNING;
803fb7
                 else
803fb7
-                        print_status_info(&info, ellipsized);
803fb7
+                        r = EXIT_PROGRAM_RUNNING_OR_SERVICE_OK;
803fb7
         }
803fb7
 
803fb7
         strv_free(info.documentation);
803fb7
         strv_free(info.dropin_paths);
803fb7
         strv_free(info.listen);
803fb7
 
803fb7
-        if (!streq_ptr(info.active_state, "active") &&
803fb7
-            !streq_ptr(info.active_state, "reloading") &&
803fb7
-            streq(verb, "status")) {
803fb7
-                /* According to LSB: "program not running" */
803fb7
-                /* 0: program is running or service is OK
803fb7
-                 * 1: program is dead and /run PID file exists
803fb7
-                 * 2: program is dead and /run/lock lock file exists
803fb7
-                 * 3: program is not running
803fb7
-                 * 4: program or service status is unknown
803fb7
-                 */
803fb7
-                if (info.pid_file && access(info.pid_file, F_OK) == 0)
803fb7
-                        r = EXIT_PROGRAM_DEAD_AND_PID_EXISTS;
803fb7
-                else if (streq_ptr(info.load_state, "not-found") && streq_ptr(info.active_state, "inactive"))
803fb7
-                        r = EXIT_PROGRAM_OR_SERVICES_STATUS_UNKNOWN;
803fb7
-                else
803fb7
-                        r = EXIT_PROGRAM_NOT_RUNNING;
803fb7
-        }
803fb7
-
803fb7
         while ((p = info.exec)) {
803fb7
                 LIST_REMOVE(exec, info.exec, p);
803fb7
                 exec_status_info_free(p);
803fb7
@@ -4394,7 +4423,7 @@ static int show_all(
803fb7
                 if (!p)
803fb7
                         return log_oom();
803fb7
 
803fb7
-                r = show_one(verb, bus, p, show_properties, new_line, ellipsized);
803fb7
+                r = show_one(verb, bus, p, u->id, show_properties, new_line, ellipsized);
803fb7
                 if (r < 0)
803fb7
                         return r;
803fb7
                 else if (r > 0 && ret == 0)
803fb7
@@ -4481,9 +4510,8 @@ static int show(sd_bus *bus, char **args) {
803fb7
                 setrlimit_closest(RLIMIT_NOFILE, &RLIMIT_MAKE_CONST(16384));
803fb7
 
803fb7
         /* If no argument is specified inspect the manager itself */
803fb7
-
803fb7
         if (show_properties && strv_length(args) <= 1)
803fb7
-                return show_one(args[0], bus, "/org/freedesktop/systemd1", show_properties, &new_line, &ellipsized);
803fb7
+                return show_one(args[0], bus, "/org/freedesktop/systemd1", NULL, show_properties, &new_line, &ellipsized);
803fb7
 
803fb7
         if (show_status && strv_length(args) <= 1) {
803fb7
 
803fb7
@@ -4498,7 +4526,7 @@ static int show(sd_bus *bus, char **args) {
803fb7
                 char **name;
803fb7
 
803fb7
                 STRV_FOREACH(name, args + 1) {
803fb7
-                        _cleanup_free_ char *unit = NULL;
803fb7
+                        _cleanup_free_ char *path = NULL, *unit = NULL;
803fb7
                         uint32_t id;
803fb7
 
803fb7
                         if (safe_atou32(*name, &id) < 0) {
803fb7
@@ -4508,20 +4536,23 @@ static int show(sd_bus *bus, char **args) {
803fb7
                                 continue;
803fb7
                         } else if (show_properties) {
803fb7
                                 /* Interpret as job id */
803fb7
-                                if (asprintf(&unit, "/org/freedesktop/systemd1/job/%u", id) < 0)
803fb7
+                                if (asprintf(&path, "/org/freedesktop/systemd1/job/%u", id) < 0)
803fb7
                                         return log_oom();
803fb7
 
803fb7
                         } else {
803fb7
                                 /* Interpret as PID */
803fb7
-                                r = get_unit_dbus_path_by_pid(bus, id, &unit);
803fb7
+                                r = get_unit_dbus_path_by_pid(bus, id, &path);
803fb7
                                 if (r < 0) {
803fb7
                                         ret = r;
803fb7
                                         continue;
803fb7
                                 }
803fb7
+
803fb7
+                                r = unit_name_from_dbus_path(path, &unit);
803fb7
+                                if (r < 0)
803fb7
+                                        return log_oom();
803fb7
                         }
803fb7
 
803fb7
-                        r = show_one(args[0], bus, unit, show_properties,
803fb7
-                                     &new_line, &ellipsized);
803fb7
+                        r = show_one(args[0], bus, path, unit, show_properties, &new_line, &ellipsized);
803fb7
                         if (r < 0)
803fb7
                                 return r;
803fb7
                         else if (r > 0 && ret == 0)
803fb7
@@ -4536,17 +4567,16 @@ static int show(sd_bus *bus, char **args) {
803fb7
                                 log_error_errno(r, "Failed to expand names: %m");
803fb7
 
803fb7
                         STRV_FOREACH(name, names) {
803fb7
-                                _cleanup_free_ char *unit;
803fb7
+                                _cleanup_free_ char *path;
803fb7
 
803fb7
-                                unit = unit_dbus_path_from_name(*name);
803fb7
-                                if (!unit)
803fb7
+                                path = unit_dbus_path_from_name(*name);
803fb7
+                                if (!path)
803fb7
                                         return log_oom();
803fb7
 
803fb7
-                                r = show_one(args[0], bus, unit, show_properties,
803fb7
-                                             &new_line, &ellipsized);
803fb7
+                                r = show_one(args[0], bus, path, *name, show_properties, &new_line, &ellipsized);
803fb7
                                 if (r < 0)
803fb7
                                         return r;
803fb7
-                                else if (r > 0 && ret == 0)
803fb7
+                                if (r > 0 && ret == 0)
803fb7
                                         ret = r;
803fb7
                         }
803fb7
                 }