You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
7.3 KiB
216 lines
7.3 KiB
From d3706690bf2953cb8e0362253dc68d77989de3be Mon Sep 17 00:00:00 2001 |
|
From: Lukas Nykryn <lnykryn@redhat.com> |
|
Date: Fri, 11 Sep 2015 13:37:59 +0200 |
|
Subject: [PATCH] loginctl: print nontrivial properties in logictl show-* |
|
|
|
Cherry-picked from: 2a998c74028a109d6bd8888951abfa8e25a15fb1 |
|
Resolves: #1260465 |
|
--- |
|
src/login/loginctl.c | 152 ++++++++++++++++++++++++++++++++++++++++++- |
|
src/shared/macro.h | 13 ++++ |
|
2 files changed, 162 insertions(+), 3 deletions(-) |
|
|
|
diff --git a/src/login/loginctl.c b/src/login/loginctl.c |
|
index b0eede9a34..6c8a59e7c9 100644 |
|
--- a/src/login/loginctl.c |
|
+++ b/src/login/loginctl.c |
|
@@ -657,19 +657,165 @@ finish: |
|
return r; |
|
} |
|
|
|
+static int print_property(const char *name, sd_bus_message *m, const char *contents) { |
|
+ int r; |
|
+ |
|
+ assert(name); |
|
+ assert(m); |
|
+ assert(contents); |
|
+ |
|
+ if (arg_property && !strv_find(arg_property, name)) |
|
+ /* skip what we didn't read */ |
|
+ return sd_bus_message_skip(m, contents); |
|
+ |
|
+ switch (contents[0]) { |
|
+ |
|
+ case SD_BUS_TYPE_STRUCT_BEGIN: |
|
+ |
|
+ if (contents[1] == SD_BUS_TYPE_STRING && STR_IN_SET(name, "Display", "Seat", "ActiveSession")) { |
|
+ const char *s; |
|
+ |
|
+ r = sd_bus_message_read(m, "(so)", &s, NULL); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ if (arg_all || !isempty(s)) |
|
+ printf("%s=%s\n", name, s); |
|
+ |
|
+ return 0; |
|
+ |
|
+ } else if (contents[1] == SD_BUS_TYPE_UINT32 && streq(name, "User")) { |
|
+ uint32_t uid; |
|
+ |
|
+ r = sd_bus_message_read(m, "(uo)", &uid, NULL); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ if (UID_IS_INVALID(uid)) { |
|
+ log_error("Invalid user ID: " UID_FMT, uid); |
|
+ return -EINVAL; |
|
+ } |
|
+ |
|
+ printf("%s=" UID_FMT "\n", name, uid); |
|
+ |
|
+ return 0; |
|
+ } |
|
+ |
|
+ break; |
|
+ |
|
+ case SD_BUS_TYPE_ARRAY: |
|
+ |
|
+ if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "Sessions")) { |
|
+ const char *s; |
|
+ bool space = false; |
|
+ |
|
+ r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(so)"); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ printf("%s=", name); |
|
+ |
|
+ while ((r = sd_bus_message_read(m, "(so)", &s, NULL)) > 0) { |
|
+ printf("%s%s", space ? " " : "", s); |
|
+ space = true; |
|
+ } |
|
+ |
|
+ printf("\n"); |
|
+ |
|
+ 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); |
|
+ |
|
+ return 0; |
|
+ } |
|
+ |
|
+ break; |
|
+ } |
|
+ |
|
+ r = bus_print_property(name, m, arg_all); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ if (r == 0) { |
|
+ r = sd_bus_message_skip(m, contents); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ if (arg_all) |
|
+ printf("%s=[unprintable]\n", name); |
|
+ } |
|
+ |
|
+ return 0; |
|
+} |
|
+ |
|
static int show_properties(sd_bus *bus, const char *path, bool *new_line) { |
|
+ _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; |
|
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; |
|
int r; |
|
|
|
+ assert(bus); |
|
+ assert(path); |
|
+ assert(new_line); |
|
+ |
|
+ r = sd_bus_call_method( |
|
+ bus, |
|
+ "org.freedesktop.login1", |
|
+ path, |
|
+ "org.freedesktop.DBus.Properties", |
|
+ "GetAll", |
|
+ &error, |
|
+ &reply, |
|
+ "s", ""); |
|
+ if (r < 0) |
|
+ return log_error_errno(r, "Failed to get properties: %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); |
|
+ |
|
if (*new_line) |
|
printf("\n"); |
|
|
|
*new_line = true; |
|
|
|
- r = bus_print_all_properties(bus, "org.freedesktop.login1", path, arg_property, arg_all); |
|
+ while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) { |
|
+ const char *name, *contents; |
|
+ |
|
+ r = sd_bus_message_read(reply, "s", &name); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ r = sd_bus_message_peek_type(reply, NULL, &contents); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ r = print_property(name, reply, contents); |
|
+ if (r < 0) |
|
+ return r; |
|
+ |
|
+ r = sd_bus_message_exit_container(reply); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ r = sd_bus_message_exit_container(reply); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ } |
|
if (r < 0) |
|
- log_error_errno(r, "Could not get properties: %m"); |
|
+ return bus_log_parse_error(r); |
|
|
|
- return r; |
|
+ r = sd_bus_message_exit_container(reply); |
|
+ if (r < 0) |
|
+ return bus_log_parse_error(r); |
|
+ |
|
+ return 0; |
|
} |
|
|
|
static int show_session(int argc, char *argv[], void *userdata) { |
|
diff --git a/src/shared/macro.h b/src/shared/macro.h |
|
index 7f89951d62..9d857dc8d7 100644 |
|
--- a/src/shared/macro.h |
|
+++ b/src/shared/macro.h |
|
@@ -26,6 +26,7 @@ |
|
#include <sys/types.h> |
|
#include <sys/uio.h> |
|
#include <inttypes.h> |
|
+#include <stdbool.h> |
|
|
|
#define _printf_(a,b) __attribute__ ((format (printf, a, b))) |
|
#define _alloc_(...) __attribute__ ((alloc_size(__VA_ARGS__))) |
|
@@ -451,6 +452,18 @@ do { \ |
|
#define GID_INVALID ((gid_t) -1) |
|
#define MODE_INVALID ((mode_t) -1) |
|
|
|
+static inline bool UID_IS_INVALID(uid_t uid) { |
|
+ /* We consider both the old 16bit -1 user and the newer 32bit |
|
+ * -1 user invalid, since they are or used to be incompatible |
|
+ * with syscalls such as setresuid() or chown(). */ |
|
+ |
|
+ return uid == (uid_t) ((uint32_t) -1) || uid == (uid_t) ((uint16_t) -1); |
|
+} |
|
+ |
|
+static inline bool GID_IS_INVALID(gid_t gid) { |
|
+ return gid == (gid_t) ((uint32_t) -1) || gid == (gid_t) ((uint16_t) -1); |
|
+} |
|
+ |
|
#define DEFINE_TRIVIAL_CLEANUP_FUNC(type, func) \ |
|
static inline void func##p(type *p) { \ |
|
if (*p) \
|
|
|