chiark / gitweb /
util: nicer tree drawings
[elogind.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 }