summaryrefslogtreecommitdiffstats
path: root/src/login/sysfs-show.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/login/sysfs-show.c')
-rw-r--r--src/login/sysfs-show.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c
new file mode 100644
index 0000000..d79f753
--- /dev/null
+++ b/src/login/sysfs-show.c
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <errno.h>
+
+#include "sd-device.h"
+
+#include "alloc-util.h"
+#include "device-enumerator-private.h"
+#include "glyph-util.h"
+#include "path-util.h"
+#include "string-util.h"
+#include "sysfs-show.h"
+#include "terminal-util.h"
+#include "util.h"
+
+static int show_sysfs_one(
+ const char *seat,
+ sd_device **dev_list,
+ size_t *i_dev,
+ size_t n_dev,
+ const char *sub,
+ const char *prefix,
+ unsigned n_columns,
+ OutputFlags flags) {
+
+ size_t max_width;
+ int r;
+
+ assert(seat);
+ assert(dev_list);
+ assert(i_dev);
+ assert(prefix);
+
+ if (flags & OUTPUT_FULL_WIDTH)
+ max_width = SIZE_MAX;
+ else if (n_columns < 10)
+ max_width = 10;
+ else
+ max_width = n_columns;
+
+ while (*i_dev < n_dev) {
+ const char *sysfs, *sn, *name = NULL, *subsystem, *sysname;
+ _cleanup_free_ char *k = NULL, *l = NULL;
+ size_t lookahead;
+ bool is_master;
+
+ if (sd_device_get_syspath(dev_list[*i_dev], &sysfs) < 0 ||
+ !path_startswith(sysfs, sub))
+ return 0;
+
+ if (sd_device_get_property_value(dev_list[*i_dev], "ID_SEAT", &sn) < 0 || isempty(sn))
+ sn = "seat0";
+
+ /* Explicitly also check for tag 'seat' here */
+ if (!streq(seat, sn) ||
+ sd_device_has_current_tag(dev_list[*i_dev], "seat") <= 0 ||
+ sd_device_get_subsystem(dev_list[*i_dev], &subsystem) < 0 ||
+ sd_device_get_sysname(dev_list[*i_dev], &sysname) < 0) {
+ (*i_dev)++;
+ continue;
+ }
+
+ is_master = sd_device_has_current_tag(dev_list[*i_dev], "master-of-seat") > 0;
+
+ if (sd_device_get_sysattr_value(dev_list[*i_dev], "name", &name) < 0)
+ (void) sd_device_get_sysattr_value(dev_list[*i_dev], "id", &name);
+
+ /* Look if there's more coming after this */
+ for (lookahead = *i_dev + 1; lookahead < n_dev; lookahead++) {
+ const char *lookahead_sysfs;
+
+ if (sd_device_get_syspath(dev_list[lookahead], &lookahead_sysfs) < 0)
+ continue;
+
+ if (path_startswith(lookahead_sysfs, sub) &&
+ !path_startswith(lookahead_sysfs, sysfs)) {
+ const char *lookahead_sn;
+
+ if (sd_device_get_property_value(dev_list[lookahead], "ID_SEAT", &lookahead_sn) < 0 ||
+ isempty(lookahead_sn))
+ lookahead_sn = "seat0";
+
+ if (streq(seat, lookahead_sn) && sd_device_has_current_tag(dev_list[lookahead], "seat") > 0)
+ break;
+ }
+ }
+
+ k = ellipsize(sysfs, max_width, 20);
+ if (!k)
+ return -ENOMEM;
+
+ printf("%s%s%s\n", prefix, special_glyph(lookahead < n_dev ? SPECIAL_GLYPH_TREE_BRANCH : SPECIAL_GLYPH_TREE_RIGHT), k);
+
+ if (asprintf(&l,
+ "%s%s:%s%s%s%s",
+ is_master ? "[MASTER] " : "",
+ subsystem, sysname,
+ name ? " \"" : "", strempty(name), name ? "\"" : "") < 0)
+ return -ENOMEM;
+
+ free(k);
+ k = ellipsize(l, max_width, 70);
+ if (!k)
+ return -ENOMEM;
+
+ printf("%s%s%s\n", prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ", k);
+
+ if (++(*i_dev) < n_dev) {
+ _cleanup_free_ char *p = NULL;
+
+ p = strjoin(prefix, lookahead < n_dev ? special_glyph(SPECIAL_GLYPH_TREE_VERTICAL) : " ");
+ if (!p)
+ return -ENOMEM;
+
+ r = show_sysfs_one(seat, dev_list, i_dev, n_dev, sysfs, p,
+ n_columns == UINT_MAX || n_columns < 2 ? n_columns : n_columns - 2,
+ flags);
+ if (r < 0)
+ return r;
+ }
+
+ }
+
+ return 0;
+}
+
+int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
+ _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
+ size_t n_dev = 0, i = 0;
+ sd_device **dev_list;
+ int r;
+
+ if (n_columns <= 0)
+ n_columns = columns();
+
+ prefix = strempty(prefix);
+
+ if (isempty(seat))
+ seat = "seat0";
+
+ r = sd_device_enumerator_new(&e);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_allow_uninitialized(e);
+ if (r < 0)
+ return r;
+
+ r = sd_device_enumerator_add_match_tag(e, streq(seat, "seat0") ? "seat" : seat);
+ if (r < 0)
+ return r;
+
+ r = device_enumerator_scan_devices(e);
+ if (r < 0)
+ return r;
+
+ dev_list = device_enumerator_get_devices(e, &n_dev);
+
+ if (dev_list && n_dev > 0)
+ show_sysfs_one(seat, dev_list, &i, n_dev, "/", prefix, n_columns, flags);
+ else
+ printf("%s%s%s\n", prefix, special_glyph(SPECIAL_GLYPH_TREE_RIGHT), "(none)");
+
+ return 0;
+}