3 * The DragonFly Project. All rights reserved.
5 * This code is derived from software contributed to The DragonFly Project
6 * by Nolan Lum <nol888@gmail.com>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * 3. Neither the name of The DragonFly Project nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific, prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/queue.h>
48 static SLIST_HEAD(, sl_entry
) props
= SLIST_HEAD_INITIALIZER(props
);
51 SLIST_ENTRY(sl_entry
) entries
;
54 static int MonitorOpt
;
57 usage(const char *name
)
60 "usage: %s [-Ah] [-p property] [-d device] [-m key:value] [-r key:value]\n"
61 "Valid options are:\n"
63 " Don't display aliases.\n"
65 " Print this help message.\n\n"
67 " Continue monitoring after initial scan.\n\n"
68 "Valid options with their arguments are:\n"
70 " Only display property; can be specified multiple times and\n"
71 " combined with all other options.\n"
73 " Only display devices with name `device'. When used with\n"
74 " -p, only properties `-p' of device `-d' are listed. Can be\n"
75 " specified multiple times. Allows wildcards.\n"
77 " Only display devices whose property `key' matches with wildcards\n"
78 " value `value' unless the key-value pair starts with ~, in which\n"
79 " case the match is inverted. Stacks with -p, -d, and -m.\n"
80 " Can be specified multiple times.\n"
82 " Behaves similarly to `-m', but matches with regex.\n",
88 parse_args(int argc
, char *argv
[], struct udev_enumerate
*enumerate
)
96 /* p = properties to list (defaults to all) */
97 /* d = devices to list (defaults to all) */
98 /* m = display only devices in d that match these prop values */
99 /* r = display only devices in d that match these prop values (regex) */
100 while ((ch
= getopt(argc
, argv
, "AMp:d:m:r:h")) != -1) {
105 udev_enumerate_add_match_property(enumerate
, "alias",
109 ent
= malloc(sizeof(struct sl_entry
));
111 SLIST_INSERT_HEAD(&props
, ent
, entries
);
117 udev_enumerate_add_match_expr(enumerate
, "name",
122 /* Check for exclusion. */
123 invert
= *optarg
== '~';
125 /* Split into key/value. */
126 colon
= strchr(optarg
, ':');
129 "Invalid property key/value pair `%s'.\n",
137 udev_enumerate_add_nomatch_regex(enumerate
,
138 optarg
+ 1, colon
+ 1);
140 udev_enumerate_add_nomatch_expr(enumerate
,
141 optarg
+ 1, colon
+ 1);
144 udev_enumerate_add_match_regex(enumerate
,
147 udev_enumerate_add_match_expr(enumerate
,
160 print_prop(const char* key
, prop_object_t value
)
164 printf("\t%s = ", key
);
166 prop_type_t val_type
= prop_object_type(value
);
169 printf("%s\n", prop_bool_true((prop_bool_t
)value
) ?
172 case PROP_TYPE_NUMBER
:
173 if (prop_number_unsigned((prop_number_t
)value
))
174 printf("%1$"PRIu64
" (0x%1$"PRIx64
")\n",
175 prop_number_unsigned_integer_value((prop_number_t
)value
));
177 printf("%"PRId64
"\n",
178 prop_number_integer_value((prop_number_t
)value
));
180 case PROP_TYPE_STRING
:
181 val_str
= prop_string_cstring(value
);
182 printf("%s\n", val_str
);
191 main(int argc
, char* argv
[])
194 struct udev_enumerate
*enumerate
;
195 struct udev_monitor
*mon
;
196 struct udev_list_entry
*current
;
197 struct udev_device
*dev
;
198 prop_object_t key_val
;
199 prop_dictionary_t dict
;
200 prop_dictionary_keysym_t cur_key
;
201 prop_object_iterator_t iter
;
208 fprintf(stderr
, "Make sure udevd is running\n");
209 err(EX_UNAVAILABLE
, "udev_new");
212 enumerate
= udev_enumerate_new(ctx
);
213 if (enumerate
== NULL
)
214 err(EX_UNAVAILABLE
, "udev_enumerate_new");
216 parse_args(argc
, argv
, enumerate
);
219 * Don't lose any races, start monitor before scanning devices.
222 mon
= udev_monitor_new(ctx
);
223 udev_monitor_enable_receiving(mon
);
228 ret
= udev_enumerate_scan_devices(enumerate
);
230 err(EX_UNAVAILABLE
, "udev_enumerate_scan_devices ret = %d",
233 current
= udev_enumerate_get_list_entry(enumerate
);
234 if (current
== NULL
) {
235 printf("No devices found.\n");
237 udev_list_entry_foreach(current
, current
) {
238 dev
= udev_list_entry_get_device(current
);
241 dict
= udev_device_get_dictionary(dev
);
244 iter
= prop_dictionary_iterator(dict
);
247 dev_name
= prop_string_cstring(prop_dictionary_get(dict
, "name"));
248 printf("Device %s:\n", dev_name
);
251 if (!SLIST_EMPTY(&props
)) {
252 SLIST_FOREACH(ent
, &props
, entries
) {
253 key_val
= prop_dictionary_get(dict
,
256 print_prop(ent
->val
, key_val
);
259 while ((cur_key
= (prop_dictionary_keysym_t
)prop_object_iterator_next(iter
)) != NULL
) {
260 key_str
= prop_dictionary_keysym_cstring_nocopy(cur_key
);
261 key_val
= prop_dictionary_get_keysym(dict
,
263 print_prop(key_str
, key_val
);
271 udev_enumerate_unref(enumerate
);
274 while ((dev
= udev_monitor_receive_device(mon
)) != NULL
) {
275 dict
= udev_device_get_dictionary(dev
);
278 iter
= prop_dictionary_iterator(dict
);
281 dev_name
= prop_string_cstring(prop_dictionary_get(dict
, "name"));
282 printf("Device %s:\n", dev_name
);
285 if (!SLIST_EMPTY(&props
)) {
286 SLIST_FOREACH(ent
, &props
, entries
) {
287 key_val
= prop_dictionary_get(dict
,
290 print_prop(ent
->val
, key_val
);
293 while ((cur_key
= (prop_dictionary_keysym_t
)prop_object_iterator_next(iter
)) != NULL
) {
294 key_str
= prop_dictionary_keysym_cstring_nocopy(cur_key
);
295 key_val
= prop_dictionary_get_keysym(dict
,
297 print_prop(key_str
, key_val
);
303 udev_monitor_unref(mon
);