net: Factor out ASSERT_IN_NETISR and ASSERT_IS_NETISR
[dragonfly.git] / sbin / devattr / devattr.c
1 /*
2  * Copyright (c) 2010
3  *              The DragonFly Project.  All rights reserved.
4  *
5  * This code is derived from software contributed to The DragonFly Project
6  * by Nolan Lum <nol888@gmail.com>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
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
17  *        distribution.
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.
21  *
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
33  * SUCH DAMAGE.
34  */
35
36 #include <sys/queue.h>
37
38 #include <ctype.h>
39 #include <devattr.h>
40 #include <err.h>
41 #include <inttypes.h>
42 #include <string.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <sysexits.h>
46 #include <unistd.h>
47
48 static SLIST_HEAD(, sl_entry) props = SLIST_HEAD_INITIALIZER(props);
49 struct sl_entry {
50         char *val;
51         SLIST_ENTRY(sl_entry) entries;
52 } *ent;
53
54 static int MonitorOpt;
55
56 static void
57 usage(const char *name)
58 {
59         fprintf(stderr,
60             "usage: %s [-Ah] [-p property] [-d device] [-m key:value] [-r key:value]\n"
61             "Valid options are:\n"
62             " -A\n"
63             "   Don't display aliases.\n"
64             " -h\n"
65             "   Print this help message.\n\n"
66             " -M\n"
67             "   Continue monitoring after initial scan.\n\n"
68             "Valid options with their arguments are:\n"
69             " -p <property>\n"
70             "   Only display property; can be specified multiple times and\n"
71             "   combined with all other options.\n"
72             " -d <device>\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"
76             " -m <key:value>\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"
81             " -r <key:value>\n"
82             "   Behaves similarly to `-m', but matches with regex.\n",
83             name);
84         exit(EX_USAGE);
85 }
86
87 static void
88 parse_args(int argc, char *argv[], struct udev_enumerate *enumerate)
89 {
90         int ch, invert;
91         char *colon;
92
93         SLIST_INIT(&props);
94
95         /* A = no aliases */
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) {
101                 invert = false;
102
103                 switch (ch) {
104                 case 'A':
105                         udev_enumerate_add_match_property(enumerate, "alias",
106                             "0");
107                         break;
108                 case 'p':
109                         ent = malloc(sizeof(struct sl_entry));
110                         ent->val = optarg;
111                         SLIST_INSERT_HEAD(&props, ent, entries);
112                         break;
113                 case 'M':
114                         MonitorOpt = 1;
115                         break;
116                 case 'd':
117                         udev_enumerate_add_match_expr(enumerate, "name",
118                             optarg);
119                         break;
120                 case 'm':
121                 case 'r':
122                         /* Check for exclusion. */
123                         invert = *optarg == '~';
124
125                         /* Split into key/value. */
126                         colon = strchr(optarg, ':');
127                         if (colon == NULL) {
128                                 fprintf(stderr,
129                                     "Invalid property key/value pair `%s'.\n",
130                                     optarg);
131                                 return;
132                         }
133
134                         *colon = '\0';
135                         if (invert) {
136                                 if (ch == 'r')
137                                         udev_enumerate_add_nomatch_regex(enumerate,
138                                             optarg + 1, colon + 1);
139                                 else
140                                         udev_enumerate_add_nomatch_expr(enumerate,
141                                             optarg + 1, colon + 1);
142                         } else {
143                                 if (ch == 'r')
144                                         udev_enumerate_add_match_regex(enumerate,
145                                             optarg, colon + 1);
146                                 else
147                                         udev_enumerate_add_match_expr(enumerate,
148                                             optarg, colon + 1);
149                         }
150                         break;
151                 case 'h':
152                 default:
153                         usage(argv[0]);
154                 }
155         }
156         return;
157 }
158
159 static void
160 print_prop(const char* key, prop_object_t value)
161 {
162         char *val_str;
163
164         printf("\t%s = ", key);
165
166         prop_type_t val_type = prop_object_type(value);
167         switch (val_type) {
168         case PROP_TYPE_BOOL:
169                 printf("%s\n", prop_bool_true((prop_bool_t)value) ?
170                     "true" : "false");
171                 break;
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));
176                 else
177                         printf("%"PRId64"\n",
178                             prop_number_integer_value((prop_number_t)value));
179                 break;
180         case PROP_TYPE_STRING:
181                 val_str = prop_string_cstring(value);
182                 printf("%s\n", val_str);
183                 free(val_str);
184                 break;
185         default:
186                 break;
187         }
188 }
189
190 int
191 main(int argc, char* argv[])
192 {
193         struct udev *ctx;
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;
202         const char *key_str;
203         char *dev_name;
204         int ret;
205
206         ctx = udev_new();
207         if (ctx == NULL) {
208                 fprintf(stderr, "Make sure udevd is running\n");
209                 err(EX_UNAVAILABLE, "udev_new");
210         }
211
212         enumerate = udev_enumerate_new(ctx);
213         if (enumerate == NULL)
214                 err(EX_UNAVAILABLE, "udev_enumerate_new");
215
216         parse_args(argc, argv, enumerate);
217
218         /*
219          * Don't lose any races, start monitor before scanning devices.
220          */
221         if (MonitorOpt) {
222                 mon = udev_monitor_new(ctx);
223                 udev_monitor_enable_receiving(mon);
224         } else {
225                 mon = NULL;
226         }
227
228         ret = udev_enumerate_scan_devices(enumerate);
229         if (ret != 0)
230                 err(EX_UNAVAILABLE, "udev_enumerate_scan_devices ret = %d",
231                     ret);
232
233         current = udev_enumerate_get_list_entry(enumerate);
234         if (current == NULL) {
235                 printf("No devices found.\n");
236         } else {
237                 udev_list_entry_foreach(current, current) {
238                         dev = udev_list_entry_get_device(current);
239                         if (dev == NULL)
240                                 continue;
241                         dict = udev_device_get_dictionary(dev);
242                         if (dict == NULL)
243                                 continue;
244                         iter = prop_dictionary_iterator(dict);
245                         cur_key = NULL;
246
247                         dev_name = prop_string_cstring(prop_dictionary_get(dict, "name"));
248                         printf("Device %s:\n", dev_name);
249                         free(dev_name);
250
251                         if (!SLIST_EMPTY(&props)) {
252                                 SLIST_FOREACH(ent, &props, entries) {
253                                         key_val = prop_dictionary_get(dict,
254                                             ent->val);
255                                         if (key_val != NULL)
256                                                 print_prop(ent->val, key_val);
257                                 }
258                         } else {
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,
262                                             cur_key);
263                                         print_prop(key_str, key_val);
264                                 }
265                         }
266
267                         printf("\n");
268                 }
269         }
270
271         udev_enumerate_unref(enumerate);
272
273         if (mon) {
274                 while ((dev = udev_monitor_receive_device(mon)) != NULL) {
275                         dict = udev_device_get_dictionary(dev);
276                         if (dict == NULL)
277                                 continue;
278                         iter = prop_dictionary_iterator(dict);
279                         cur_key =NULL;
280
281                         dev_name = prop_string_cstring(prop_dictionary_get(dict, "name"));
282                         printf("Device %s:\n", dev_name);
283                         free(dev_name);
284
285                         if (!SLIST_EMPTY(&props)) {
286                                 SLIST_FOREACH(ent, &props, entries) {
287                                         key_val = prop_dictionary_get(dict,
288                                             ent->val);
289                                         if (key_val != NULL)
290                                                 print_prop(ent->val, key_val);
291                                 }
292                         } else {
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,
296                                             cur_key);
297                                         print_prop(key_str, key_val);
298                                 }
299                         }
300
301                         printf("\n");
302                 }
303                 udev_monitor_unref(mon);
304         }
305
306         udev_unref(ctx);
307
308         return (0);
309 }