Sync zoneinfo database with tzdata2016i from ftp://ftp.iana.org/tz/releases
[dragonfly.git] / sbin / devattr / devattr.c
blob97693fa30e32aa302e4c7ecf45db97165ce1ba0c
1 /*
2 * Copyright (c) 2010
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
10 * are met:
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.
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.
36 #include <sys/queue.h>
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>
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;
54 static int MonitorOpt;
56 static void
57 usage(const char *name)
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);
87 static void
88 parse_args(int argc, char *argv[], struct udev_enumerate *enumerate)
90 int ch, invert;
91 char *colon;
93 SLIST_INIT(&props);
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;
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 == '~';
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;
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);
150 break;
151 case 'h':
152 default:
153 usage(argv[0]);
156 return;
159 static void
160 print_prop(const char* key, prop_object_t value)
162 char *val_str;
164 printf("\t%s = ", key);
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;
191 main(int argc, char* argv[])
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;
206 ctx = udev_new();
207 if (ctx == NULL) {
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.
221 if (MonitorOpt) {
222 mon = udev_monitor_new(ctx);
223 udev_monitor_enable_receiving(mon);
224 } else {
225 mon = NULL;
228 ret = udev_enumerate_scan_devices(enumerate);
229 if (ret != 0)
230 err(EX_UNAVAILABLE, "udev_enumerate_scan_devices ret = %d",
231 ret);
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;
247 dev_name = prop_string_cstring(prop_dictionary_get(dict, "name"));
248 printf("Device %s:\n", dev_name);
249 free(dev_name);
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);
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);
267 printf("\n");
271 udev_enumerate_unref(enumerate);
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;
281 dev_name = prop_string_cstring(prop_dictionary_get(dict, "name"));
282 printf("Device %s:\n", dev_name);
283 free(dev_name);
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);
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);
301 printf("\n");
303 udev_monitor_unref(mon);
306 udev_unref(ctx);
308 return (0);