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