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