chiark / gitweb /
loginctl: implement more verbs
[elogind.git] / src / 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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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
29 static bool device_has_tag(struct udev_device *d, const char *tag) {
30         struct udev_list_entry *first, *item;
31
32         assert(d);
33         assert(tag);
34
35         /* FIXME */
36         udev_device_get_is_initialized(d);
37
38         first = udev_device_get_tags_list_entry(d);
39         udev_list_entry_foreach(item, first)
40                 if (streq(udev_list_entry_get_name(item), tag))
41                         return true;
42
43         return false;
44 }
45
46 static int show_sysfs_one(
47                 struct udev *udev,
48                 const char *seat,
49                 struct udev_list_entry **item,
50                 const char *sub,
51                 const char *prefix,
52                 unsigned n_columns) {
53
54         assert(udev);
55         assert(seat);
56         assert(item);
57         assert(prefix);
58
59         while (*item) {
60                 struct udev_list_entry *next, *lookahead;
61                 struct udev_device *d;
62                 const char *sn, *name, *sysfs, *subsystem, *sysname;
63                 char *l, *k;
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                 /* fixme, also check for tag 'seat' here */
80                 if (!streq(seat, sn) || !device_has_tag(d, "seat")) {
81                         udev_device_unref(d);
82                         *item = udev_list_entry_get_next(*item);
83                         continue;
84                 }
85
86                 name = udev_device_get_sysattr_value(d, "name");
87                 if (!name)
88                         name = udev_device_get_sysattr_value(d, "id");
89                 subsystem = udev_device_get_subsystem(d);
90                 sysname = udev_device_get_sysname(d);
91
92                 /* Look if there's more coming after this */
93                 lookahead = next = udev_list_entry_get_next(*item);
94                 while (lookahead) {
95                         const char *lookahead_sysfs;
96
97                         lookahead_sysfs = udev_list_entry_get_name(lookahead);
98
99                         if (path_startswith(lookahead_sysfs, sub) &&
100                             !path_startswith(lookahead_sysfs, sysfs)) {
101                                 struct udev_device *lookahead_d;
102
103                                 lookahead_d = udev_device_new_from_syspath(udev, lookahead_sysfs);
104                                 if (lookahead_d) {
105                                         const char *lookahead_sn;
106                                         bool found;
107
108                                         lookahead_sn = udev_device_get_property_value(d, "ID_SEAT");
109                                         if (isempty(lookahead_sn))
110                                                 lookahead_sn = "seat0";
111
112                                         found = streq(seat, lookahead_sn) && device_has_tag(lookahead_d, "seat");
113                                         udev_device_unref(lookahead_d);
114
115                                         if (found)
116                                                 break;
117                                 }
118                         }
119
120                         lookahead = udev_list_entry_get_next(lookahead);
121                 }
122
123                 k = ellipsize(sysfs, n_columns, 20);
124                 printf("%s%s %s\n", prefix, lookahead ? "\342\224\234" : "\342\224\224", k ? k : sysfs);
125                 free(k);
126
127                 if (asprintf(&l,
128                              "(%s:%s)%s%s%s",
129                              subsystem, sysname,
130                              name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) {
131                         udev_device_unref(d);
132                         return -ENOMEM;
133                 }
134
135                 k = ellipsize(l, n_columns, 70);
136                 printf("%s%s %s\n", prefix, lookahead ? "\342\224\202" : " ", k ? k : l);
137                 free(k);
138                 free(l);
139
140                 *item = next;
141                 if (*item) {
142                         char *p;
143
144                         p = strappend(prefix, lookahead ? "\342\224\202 " : "  ");
145                         show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2);
146                         free(p);
147                 }
148
149                 udev_device_unref(d);
150         }
151
152         return 0;
153 }
154
155 int show_sysfs(const char *seat, const char *prefix, unsigned n_columns) {
156         struct udev *udev;
157         struct udev_list_entry *first = NULL;
158         struct udev_enumerate *e;
159         int r;
160
161         if (n_columns <= 0)
162                 n_columns = columns();
163
164         if (!prefix)
165                 prefix = "";
166
167         if (isempty(seat))
168                 seat = "seat0";
169
170         udev = udev_new();
171         if (!udev)
172                 return -ENOMEM;
173
174         e = udev_enumerate_new(udev);
175         if (!e) {
176                 r = -ENOMEM;
177                 goto finish;
178         }
179
180         if (!streq(seat, "seat0"))
181                 r = udev_enumerate_add_match_tag(e, seat);
182         else
183                 r = udev_enumerate_add_match_tag(e, "seat");
184
185         r = udev_enumerate_scan_devices(e);
186         if (r < 0)
187                 goto finish;
188
189         first = udev_enumerate_get_list_entry(e);
190         if (first)
191                 show_sysfs_one(udev, seat, &first, "/", prefix, n_columns);
192
193 finish:
194         if (e)
195                 udev_enumerate_unref(e);
196
197         if (udev)
198                 udev_unref(udev);
199
200         return r;
201 }