]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/login/sysfs-show.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / login / sysfs-show.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <string.h>
23
24 #include "libudev.h"
25
26 #include "alloc-util.h"
27 #include "locale-util.h"
28 #include "path-util.h"
29 #include "string-util.h"
30 #include "sysfs-show.h"
31 #include "terminal-util.h"
32 #include "udev-util.h"
33 #include "util.h"
34
35 static int show_sysfs_one(
36 struct udev *udev,
37 const char *seat,
38 struct udev_list_entry **item,
39 const char *sub,
40 const char *prefix,
41 unsigned n_columns,
42 OutputFlags flags) {
43
44 size_t max_width;
45
46 assert(udev);
47 assert(seat);
48 assert(item);
49 assert(prefix);
50
51 if (flags & OUTPUT_FULL_WIDTH)
52 max_width = (size_t) -1;
53 else if (n_columns < 10)
54 max_width = 10;
55 else
56 max_width = n_columns;
57
58 while (*item) {
59 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
60 struct udev_list_entry *next, *lookahead;
61 const char *sn, *name, *sysfs, *subsystem, *sysname;
62 _cleanup_free_ char *k = NULL, *l = NULL;
63 bool is_master;
64
65 sysfs = udev_list_entry_get_name(*item);
66 if (!path_startswith(sysfs, sub))
67 return 0;
68
69 d = udev_device_new_from_syspath(udev, sysfs);
70 if (!d) {
71 *item = udev_list_entry_get_next(*item);
72 continue;
73 }
74
75 sn = udev_device_get_property_value(d, "ID_SEAT");
76 if (isempty(sn))
77 sn = "seat0";
78
79 /* Explicitly also check for tag 'seat' here */
80 if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) {
81 *item = udev_list_entry_get_next(*item);
82 continue;
83 }
84
85 is_master = udev_device_has_tag(d, "master-of-seat");
86
87 name = udev_device_get_sysattr_value(d, "name");
88 if (!name)
89 name = udev_device_get_sysattr_value(d, "id");
90 subsystem = udev_device_get_subsystem(d);
91 sysname = udev_device_get_sysname(d);
92
93 /* Look if there's more coming after this */
94 lookahead = next = udev_list_entry_get_next(*item);
95 while (lookahead) {
96 const char *lookahead_sysfs;
97
98 lookahead_sysfs = udev_list_entry_get_name(lookahead);
99
100 if (path_startswith(lookahead_sysfs, sub) &&
101 !path_startswith(lookahead_sysfs, sysfs)) {
102 _cleanup_udev_device_unref_ struct udev_device *lookahead_d = NULL;
103
104 lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
105 if (lookahead_d) {
106 const char *lookahead_sn;
107
108 lookahead_sn = udev_device_get_property_value(d, "ID_SEAT");
109 if (isempty(lookahead_sn))
110 lookahead_sn = "seat0";
111
112 if (streq(seat, lookahead_sn) && udev_device_has_tag(lookahead_d, "seat"))
113 break;
114 }
115 }
116
117 lookahead = udev_list_entry_get_next(lookahead);
118 }
119
120 k = ellipsize(sysfs, max_width, 20);
121 if (!k)
122 return -ENOMEM;
123
124 printf("%s%s%s\n", prefix, special_glyph(lookahead ? TREE_BRANCH : TREE_RIGHT), k);
125
126 if (asprintf(&l,
127 "%s%s:%s%s%s%s",
128 is_master ? "[MASTER] " : "",
129 subsystem, sysname,
130 name ? " \"" : "", strempty(name), name ? "\"" : "") < 0)
131 return -ENOMEM;
132
133 free(k);
134 k = ellipsize(l, max_width, 70);
135 if (!k)
136 return -ENOMEM;
137
138 printf("%s%s%s\n", prefix, lookahead ? special_glyph(TREE_VERTICAL) : " ", k);
139
140 *item = next;
141 if (*item) {
142 _cleanup_free_ char *p = NULL;
143
144 p = strappend(prefix, lookahead ? special_glyph(TREE_VERTICAL) : " ");
145 if (!p)
146 return -ENOMEM;
147
148 show_sysfs_one(udev, seat, item, sysfs, p,
149 n_columns == (unsigned) -1 || n_columns < 2 ? n_columns : n_columns - 2,
150 flags);
151 }
152 }
153
154 return 0;
155 }
156
157 int show_sysfs(const char *seat, const char *prefix, unsigned n_columns, OutputFlags flags) {
158 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
159 _cleanup_udev_unref_ struct udev *udev = NULL;
160 struct udev_list_entry *first = NULL;
161 int r;
162
163 if (n_columns <= 0)
164 n_columns = columns();
165
166 prefix = strempty(prefix);
167
168 if (isempty(seat))
169 seat = "seat0";
170
171 udev = udev_new();
172 if (!udev)
173 return -ENOMEM;
174
175 e = udev_enumerate_new(udev);
176 if (!e)
177 return -ENOMEM;
178
179 if (!streq(seat, "seat0"))
180 r = udev_enumerate_add_match_tag(e, seat);
181 else
182 r = udev_enumerate_add_match_tag(e, "seat");
183 if (r < 0)
184 return r;
185
186 r = udev_enumerate_add_match_is_initialized(e);
187 if (r < 0)
188 return r;
189
190 r = udev_enumerate_scan_devices(e);
191 if (r < 0)
192 return r;
193
194 first = udev_enumerate_get_list_entry(e);
195 if (first)
196 show_sysfs_one(udev, seat, &first, "/", prefix, n_columns, flags);
197 else
198 printf("%s%s%s\n", prefix, special_glyph(TREE_RIGHT), "(none)");
199
200 return r;
201 }